From 16ff508443426547cd514c4b99c90c0d7940a9b9 Mon Sep 17 00:00:00 2001 From: EggMuncherSupreme Date: Tue, 23 Apr 2024 06:53:04 +1000 Subject: [PATCH 01/30] Added the triageMove() flag to Bouncy Bubble --- src/data/move.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/data/move.ts b/src/data/move.ts index 79364fb41d0..969f7f1c558 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -5641,7 +5641,8 @@ export function initMoves() { new AttackMove(Moves.PIKA_PAPOW, Type.ELECTRIC, MoveCategory.SPECIAL, -1, -1, 20, -1, 0, 7) .attr(FriendshipPowerAttr), new AttackMove(Moves.BOUNCY_BUBBLE, Type.WATER, MoveCategory.SPECIAL, 60, 100, 20, -1, 0, 7) - .attr(HitHealAttr), + .attr(HitHealAttr) + .triageMove(), new AttackMove(Moves.BUZZY_BUZZ, Type.ELECTRIC, MoveCategory.SPECIAL, 60, 100, 20, 100, 0, 7) .attr(StatusEffectAttr, StatusEffect.PARALYSIS), new AttackMove(Moves.SIZZLY_SLIDE, Type.FIRE, MoveCategory.PHYSICAL, 60, 100, 20, 100, 0, 7) From c82f46cc88f4f6212e92b3b282914ee3942b05a9 Mon Sep 17 00:00:00 2001 From: maru Date: Tue, 23 Apr 2024 19:31:40 -0400 Subject: [PATCH 02/30] Update deploy job --- .github/workflows/deploy.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index aad509c3a7e..11b970150eb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -28,11 +28,6 @@ jobs: ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts - name: Deploy build on server if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch - run: rsync -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }} - - name: Purge Cloudflare Cache - if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch - id: purge-cache - uses: NathanVaughn/actions-cloudflare-purge@v3.1.0 - with: - cf_auth: ${{ secrets.CLOUDFLARE_API_TOKEN }} - cf_zone: ${{ secrets.CLOUDFLARE_ZONE_ID }} + run: | + rsync -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }} + ssh -t ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/prmanifest --inpath ${{ secrets.DESTINATION_DIR }} --outpath ${{ secrets.DESTINATION_DIR }}/manifest.json" From e608cb67387d0299a73f39b168ff4afe746fd1cb Mon Sep 17 00:00:00 2001 From: maru Date: Tue, 23 Apr 2024 19:36:17 -0400 Subject: [PATCH 03/30] Add --del flag to rsync in deploy job --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 11b970150eb..db8fa2777e5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -29,5 +29,5 @@ jobs: - name: Deploy build on server if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch run: | - rsync -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }} + rsync --del -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }} ssh -t ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/prmanifest --inpath ${{ secrets.DESTINATION_DIR }} --outpath ${{ secrets.DESTINATION_DIR }}/manifest.json" From ba71d2750bcaa8a81d4f1aeb75ae930e6ee9b217 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Tue, 23 Apr 2024 22:00:23 -0400 Subject: [PATCH 04/30] Load files from manifest for caching --- public/images/pokemon/variant/31_1.png | Bin 36574 -> 31729 bytes src/battle-scene.ts | 20 +++++++++++---- src/data/battle-anims.ts | 14 +++++------ src/data/move.ts | 4 +-- src/data/pokemon-species.ts | 2 +- src/field/pokemon.ts | 4 +-- src/loading-scene.ts | 7 +----- src/main.ts | 18 ++++++++++++-- src/phases.ts | 4 +-- src/plugins/cache-busted-loader-plugin.ts | 21 +++++++++------- src/scene-base.ts | 29 ++++++++++++++-------- 11 files changed, 77 insertions(+), 46 deletions(-) diff --git a/public/images/pokemon/variant/31_1.png b/public/images/pokemon/variant/31_1.png index 082e2a3d1b93666e5a5a6cbf1e35a9c2301b1bbb..d471b062136237880993516dce46777b1518251a 100644 GIT binary patch literal 31729 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 SxdzdMlLx{GWms res.json()).then(v => Object.keys(v).forEach(k => variantData[k] = v[k])); + await this.cachedFetch('./images/pokemon/variant/_masterlist.json').then(res => res.json()).then(v => Object.keys(v).forEach(k => variantData[k] = v[k])); } create() { @@ -468,8 +468,8 @@ export default class BattleScene extends SceneBase { Promise.all([ Promise.all(loadPokemonAssets), - initCommonAnims().then(() => loadCommonAnimAssets(this, true)), - Promise.all([ Moves.TACKLE, Moves.TAIL_WHIP, Moves.FOCUS_ENERGY, Moves.STRUGGLE ].map(m => initMoveAnim(m))).then(() => loadMoveAnimAssets(this, defaultMoves, true)), + initCommonAnims(this).then(() => loadCommonAnimAssets(this, true)), + Promise.all([ Moves.TACKLE, Moves.TAIL_WHIP, Moves.FOCUS_ENERGY, Moves.STRUGGLE ].map(m => initMoveAnim(this, m))).then(() => loadMoveAnimAssets(this, defaultMoves, true)), this.initStarterColors() ]).then(() => { this.pushPhase(new LoginPhase(this)); @@ -505,19 +505,29 @@ export default class BattleScene extends SceneBase { async initExpSprites(): Promise { if (expSpriteKeys.length) return; - fetch('./exp-sprites.json').then(res => res.json()).then(keys => { + this.cachedFetch('./exp-sprites.json').then(res => res.json()).then(keys => { if (Array.isArray(keys)) expSpriteKeys.push(...keys); Promise.resolve(); }); } + cachedFetch(url: string, init?: RequestInit): Promise { + const manifest = this.game['manifest']; + if (manifest) { + const timestamp = manifest[`/${url.replace('./', '')}`]; + if (timestamp) + url += `?t=${timestamp}`; + } + return fetch(url, init); + } + initStarterColors(): Promise { return new Promise(resolve => { if (starterColors) return resolve(); - fetch('./starter-colors.json').then(res => res.json()).then(sc => { + this.cachedFetch('./starter-colors.json').then(res => res.json()).then(sc => { starterColors = {}; Object.keys(sc).forEach(key => { starterColors[key] = sc[key]; diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index 8118f385fc3..db00ea600fd 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -424,14 +424,14 @@ export const moveAnims = new Map() export const chargeAnims = new Map(); export const commonAnims = new Map(); -export function initCommonAnims(): Promise { +export function initCommonAnims(scene: BattleScene): Promise { return new Promise(resolve => { const commonAnimNames = Utils.getEnumKeys(CommonAnim); const commonAnimIds = Utils.getEnumValues(CommonAnim); const commonAnimFetches = []; for (let ca = 0; ca < commonAnimIds.length; ca++) { const commonAnimId = commonAnimIds[ca]; - commonAnimFetches.push(fetch(`./battle-anims/common-${commonAnimNames[ca].toLowerCase().replace(/\_/g, '-')}.json`) + commonAnimFetches.push(scene.cachedFetch(`./battle-anims/common-${commonAnimNames[ca].toLowerCase().replace(/\_/g, '-')}.json`) .then(response => response.json()) .then(cas => commonAnims.set(commonAnimId, new AnimConfig(cas)))); } @@ -439,7 +439,7 @@ export function initCommonAnims(): Promise { }); } -export function initMoveAnim(move: Moves): Promise { +export function initMoveAnim(scene: BattleScene, move: Moves): Promise { return new Promise(resolve => { if (moveAnims.has(move)) { if (moveAnims.get(move) !== null) @@ -460,7 +460,7 @@ export function initMoveAnim(move: Moves): Promise { const defaultMoveAnim = allMoves[move] instanceof AttackMove ? Moves.TACKLE : allMoves[move] instanceof SelfStatusMove ? Moves.FOCUS_ENERGY : Moves.TAIL_WHIP; const moveName = Moves[move].toLowerCase().replace(/\_/g, '-'); const fetchAnimAndResolve = (move: Moves) => { - fetch(`./battle-anims/${moveName}.json`) + scene.cachedFetch(`./battle-anims/${moveName}.json`) .then(response => { if (!response.ok) { console.error(`Could not load animation file for move '${moveName}'`, response.status, response.statusText); @@ -477,7 +477,7 @@ export function initMoveAnim(move: Moves): Promise { populateMoveAnim(move, ba); const chargeAttr = allMoves[move].getAttrs(ChargeAttr).find(() => true) as ChargeAttr || allMoves[move].getAttrs(DelayedAttackAttr).find(() => true) as DelayedAttackAttr; if (chargeAttr) - initMoveChargeAnim(chargeAttr.chargeAnim).then(() => resolve()); + initMoveChargeAnim(scene, chargeAttr.chargeAnim).then(() => resolve()); else resolve(); }); @@ -487,7 +487,7 @@ export function initMoveAnim(move: Moves): Promise { }); } -export function initMoveChargeAnim(chargeAnim: ChargeAnim): Promise { +export function initMoveChargeAnim(scene: BattleScene, chargeAnim: ChargeAnim): Promise { return new Promise(resolve => { if (chargeAnims.has(chargeAnim)) { if (chargeAnims.get(chargeAnim) !== null) @@ -502,7 +502,7 @@ export function initMoveChargeAnim(chargeAnim: ChargeAnim): Promise { } } else { chargeAnims.set(chargeAnim, null); - fetch(`./battle-anims/${ChargeAnim[chargeAnim].toLowerCase().replace(/\_/g, '-')}.json`) + scene.cachedFetch(`./battle-anims/${ChargeAnim[chargeAnim].toLowerCase().replace(/\_/g, '-')}.json`) .then(response => response.json()) .then(ca => { if (Array.isArray(ca)) { diff --git a/src/data/move.ts b/src/data/move.ts index 9445b188b0b..48714d00c07 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -3096,7 +3096,7 @@ export class RandomMoveAttr extends OverrideMoveEffectAttr { : [ moveTargets.targets[user.randSeedInt(moveTargets.targets.length)] ]; user.getMoveQueue().push({ move: moveId, targets: targets, ignorePP: true }); user.scene.unshiftPhase(new MovePhase(user.scene, user, targets, new PokemonMove(moveId, 0, 0, true), true)); - initMoveAnim(moveId).then(() => { + initMoveAnim(user.scene, moveId).then(() => { loadMoveAnimAssets(user.scene, [ moveId ], true) .then(() => resolve(true)); }); @@ -3239,7 +3239,7 @@ export class NaturePowerAttr extends OverrideMoveEffectAttr { user.getMoveQueue().push({ move: moveId, targets: [target.getBattlerIndex()], ignorePP: true }); user.scene.unshiftPhase(new MovePhase(user.scene, user, [target.getBattlerIndex()], new PokemonMove(moveId, 0, 0, true), true)); - initMoveAnim(moveId).then(() => { + initMoveAnim(user.scene, moveId).then(() => { loadMoveAnimAssets(user.scene, [ moveId ], true) .then(() => resolve(true)); }); diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index ed55bbf4d74..ceeca373b97 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -394,7 +394,7 @@ export abstract class PokemonSpeciesForm { return new Promise(resolve => { if (variantColorCache.hasOwnProperty(key)) return resolve(); - fetch(`./images/pokemon/variant/${spritePath}.json`).then(res => res.json()).then(c => { + scene.cachedFetch(`./images/pokemon/variant/${spritePath}.json`).then(res => res.json()).then(c => { variantColorCache[key] = c; resolve(); }); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 0989c769f0f..97b228a24ca 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -275,7 +275,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { loadAssets(ignoreOverride: boolean = true): Promise { return new Promise(resolve => { const moveIds = this.getMoveset().map(m => m.getMove().id); - Promise.allSettled(moveIds.map(m => initMoveAnim(m))) + Promise.allSettled(moveIds.map(m => initMoveAnim(this.scene, m))) .then(() => { loadMoveAnimAssets(this.scene, moveIds); this.getSpeciesForm().loadAssets(this.scene, this.getGender() === Gender.FEMALE, this.formIndex, this.shiny, this.variant); @@ -317,7 +317,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (variantSet && variantSet[this.variant] === 1) { if (variantColorCache.hasOwnProperty(key)) return resolve(); - fetch(`./images/pokemon/variant/${battleSpritePath}.json`).then(res => res.json()).then(c => { + this.scene.cachedFetch(`./images/pokemon/variant/${battleSpritePath}.json`).then(res => res.json()).then(c => { variantColorCache[key] = c; resolve(); }); diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 74deaa5fdbd..38f82ff060e 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -19,12 +19,7 @@ export class LoadingScene extends SceneBase { } preload() { - const indexFile = Array.from(document.querySelectorAll('script')).map(s => s.src).find(s => /\/index/.test(s)); - if (indexFile) { - const buildIdMatch = /index\-(.*?)\.js$/.exec(indexFile); - if (buildIdMatch) - this.load['cacheBuster'] = buildIdMatch[1]; - } + this.load['manifest'] = this.game['manifest']; if (!isMobile()) this.load.video('intro_dark', 'images/intro_dark.mp4', true); diff --git a/src/main.ts b/src/main.ts index 13aa5076ff4..6a00693fc71 100644 --- a/src/main.ts +++ b/src/main.ts @@ -76,7 +76,21 @@ Phaser.GameObjects.Rectangle.prototype.setPositionRelative = setPositionRelative document.fonts.load('16px emerald').then(() => document.fonts.load('10px pkmnems')); -const game = new Phaser.Game(config); -game.sound.pauseOnBlur = false; +let game; + +const startGame = () => { + game = new Phaser.Game(config); + game.sound.pauseOnBlur = false; +}; + +fetch('/manifest.json') + .then(res => res.json()) + .then(jsonResponse => { + startGame(); + game['manifest'] = jsonResponse.manifest; + }).catch(() => { + // Manifest not found (likely local build) + startGame(); + }); export default game; diff --git a/src/phases.ts b/src/phases.ts index 62e53d79717..09595cc0ee6 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2613,7 +2613,7 @@ export class MoveAnimTestPhase extends BattlePhase { } else if (player) console.log(Moves[moveId]); - initMoveAnim(moveId).then(() => { + initMoveAnim(this, moveId).then(() => { loadMoveAnimAssets(this.scene, [ moveId ], true) .then(() => { new MoveAnim(moveId, player ? this.scene.getPlayerPokemon() : this.scene.getEnemyPokemon(), (player !== (allMoves[moveId] instanceof SelfStatusMove) ? this.scene.getEnemyPokemon() : this.scene.getPlayerPokemon()).getBattlerIndex()).play(this.scene, () => { @@ -3675,7 +3675,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { if (emptyMoveIndex > -1) { pokemon.setMove(emptyMoveIndex, this.moveId); - initMoveAnim(this.moveId).then(() => { + initMoveAnim(this, this.moveId).then(() => { loadMoveAnimAssets(this.scene, [ this.moveId ], true) .then(() => { this.scene.ui.setMode(messageMode).then(() => { diff --git a/src/plugins/cache-busted-loader-plugin.ts b/src/plugins/cache-busted-loader-plugin.ts index e1ee78709df..449c99454c2 100644 --- a/src/plugins/cache-busted-loader-plugin.ts +++ b/src/plugins/cache-busted-loader-plugin.ts @@ -1,26 +1,29 @@ -let cacheBuster = ''; - -const ignoredFiles = [ 'intro_dark' ]; +let manifest: object; export default class CacheBustedLoaderPlugin extends Phaser.Loader.LoaderPlugin { constructor(scene: Phaser.Scene) { super(scene) } - get cacheBuster() { - return cacheBuster + get manifest() { + return manifest; } - set cacheBuster(version) { - cacheBuster = version + set manifest(manifestObj: object) { + manifest = manifestObj; } addFile(file): void { if (!Array.isArray(file)) file = [ file ]; - if (!ignoredFiles.includes(file?.key) && cacheBuster) - file.forEach(item => item.url += '?v=' + cacheBuster); + file.forEach(item => { + if (manifest) { + const timestamp = manifest[`/${item.url.replace(/\/\//g, '/')}` ]; + if (timestamp) + item.url += `?t=${timestamp}`; + } + }); super.addFile(file); } diff --git a/src/scene-base.ts b/src/scene-base.ts index 1098788c42e..a990492f57b 100644 --- a/src/scene-base.ts +++ b/src/scene-base.ts @@ -5,25 +5,35 @@ export class SceneBase extends Phaser.Scene { super(config); } + getCachedUrl(url: string): string { + const manifest = this.game['manifest']; + if (manifest) { + const timestamp = manifest[`/${url}`]; + if (timestamp) + url += `?t=${timestamp}`; + } + return url; + } + loadImage(key: string, folder: string, filename?: string) { if (!filename) filename = `${key}.png`; - this.load.image(key, `images/${folder}/${filename}`); + this.load.image(key, this.getCachedUrl(`images/${folder}/${filename}`)); if (folder.startsWith('ui')) { legacyCompatibleImages.push(key); folder = folder.replace('ui', 'ui/legacy'); - this.load.image(`${key}_legacy`, `images/${folder}/${filename}`); + this.load.image(`${key}_legacy`, this.getCachedUrl(`images/${folder}/${filename}`)); } } loadSpritesheet(key: string, folder: string, size: integer, filename?: string) { if (!filename) filename = `${key}.png`; - this.load.spritesheet(key, `images/${folder}/${filename}`, { frameWidth: size, frameHeight: size }); + this.load.spritesheet(key, this.getCachedUrl(`images/${folder}/${filename}`), { frameWidth: size, frameHeight: size }); if (folder.startsWith('ui')) { legacyCompatibleImages.push(key); folder = folder.replace('ui', 'ui/legacy'); - this.load.spritesheet(`${key}_legacy`, `images/${folder}/${filename}`, { frameWidth: size, frameHeight: size }); + this.load.spritesheet(`${key}_legacy`, this.getCachedUrl(`images/${folder}/${filename}`), { frameWidth: size, frameHeight: size }); } } @@ -32,11 +42,11 @@ export class SceneBase extends Phaser.Scene { filenameRoot = key; if (folder) folder += '/'; - this.load.atlas(key, `images/${folder}${filenameRoot}.png`, `images/${folder}/${filenameRoot}.json`); + this.load.atlas(key, this.getCachedUrl(`images/${folder}${filenameRoot}.png`), this.getCachedUrl(`images/${folder}/${filenameRoot}.json`)); if (folder.startsWith('ui')) { legacyCompatibleImages.push(key); folder = folder.replace('ui', 'ui/legacy'); - this.load.atlas(`${key}_legacy`, `images/${folder}${filenameRoot}.png`, `images/${folder}/${filenameRoot}.json`); + this.load.atlas(`${key}_legacy`, this.getCachedUrl(`images/${folder}${filenameRoot}.png`), this.getCachedUrl(`images/${folder}/${filenameRoot}.json`)); } } @@ -49,14 +59,13 @@ export class SceneBase extends Phaser.Scene { folder += '/'; if (!Array.isArray(filenames)) filenames = [ filenames ]; - for (let f of filenames as string[]) { - this.load.audio(key, `audio/se/${folder}${f}`); - } + for (let f of filenames as string[]) + this.load.audio(key, this.getCachedUrl(`audio/se/${folder}${f}`)); } loadBgm(key: string, filename?: string) { if (!filename) filename = `${key}.mp3`; - this.load.audio(key, `audio/bgm/${filename}`); + this.load.audio(key, this.getCachedUrl(`audio/bgm/${filename}`)); } } \ No newline at end of file From 1376ea4e8711300f1aa83a82665d7e073adda97f Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Tue, 23 Apr 2024 22:16:49 -0400 Subject: [PATCH 05/30] Fix initial starters not having first ability unlocked --- src/system/game-data.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 0c176e446d9..c5e6dce2993 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -348,6 +348,7 @@ export class GameData { if ([ '1.0.0', '1.0.1' ].includes(systemData.gameVersion)) this.migrateStarterAbilities(systemData); this.fixVariantData(systemData); + this.fixStarterData(systemData); // Migrate ability starter data if empty for caught species Object.keys(systemData.starterData).forEach(sd => { if (systemData.dexData[sd].caughtAttr && !systemData.starterData[sd].abilityAttr) @@ -984,7 +985,7 @@ export class GameData { moveset: null, eggMoves: 0, candyCount: 0, - abilityAttr: 0, + abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILTIY_1 : 0, passiveAttr: 0, valueReduction: 0 }; @@ -1291,4 +1292,9 @@ export class GameData { } } } + + fixStarterData(systemData: SystemSaveData): void { + for (let starterId of defaultStarterSpecies) + systemData.starterData[starterId].abilityAttr |= AbilityAttr.ABILITY_1; + } } \ No newline at end of file From e2effee43db19796bdc45bbe049f3c4d84150cc8 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Tue, 23 Apr 2024 22:32:04 -0400 Subject: [PATCH 06/30] Fix typo --- src/system/game-data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/system/game-data.ts b/src/system/game-data.ts index c5e6dce2993..3a3077fadc1 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -985,7 +985,7 @@ export class GameData { moveset: null, eggMoves: 0, candyCount: 0, - abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILTIY_1 : 0, + abilityAttr: defaultStarterSpecies.includes(speciesId) ? AbilityAttr.ABILITY_1 : 0, passiveAttr: 0, valueReduction: 0 }; From 3e296116bbaa1225fb16a36ca61d1d20219b32f7 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Tue, 23 Apr 2024 23:28:55 -0400 Subject: [PATCH 07/30] Fix passing wrong argument when initializing move animations --- src/phases.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 09595cc0ee6..32106bb89df 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2613,7 +2613,7 @@ export class MoveAnimTestPhase extends BattlePhase { } else if (player) console.log(Moves[moveId]); - initMoveAnim(this, moveId).then(() => { + initMoveAnim(this.scene, moveId).then(() => { loadMoveAnimAssets(this.scene, [ moveId ], true) .then(() => { new MoveAnim(moveId, player ? this.scene.getPlayerPokemon() : this.scene.getEnemyPokemon(), (player !== (allMoves[moveId] instanceof SelfStatusMove) ? this.scene.getEnemyPokemon() : this.scene.getPlayerPokemon()).getBattlerIndex()).play(this.scene, () => { @@ -3675,7 +3675,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { if (emptyMoveIndex > -1) { pokemon.setMove(emptyMoveIndex, this.moveId); - initMoveAnim(this, this.moveId).then(() => { + initMoveAnim(this.scene, this.moveId).then(() => { loadMoveAnimAssets(this.scene, [ this.moveId ], true) .then(() => { this.scene.ui.setMode(messageMode).then(() => { From 9024eeb990c6cd09c7d4d4fa76db3acea934ccdb Mon Sep 17 00:00:00 2001 From: Samuel H Date: Wed, 24 Apr 2024 00:25:01 -0400 Subject: [PATCH 08/30] Aggregate Stat Changes (#266) * Add stat change aggregation * Minor fixes to stat change aggregation --- src/phases.ts | 72 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/src/phases.ts b/src/phases.ts index 32106bb89df..e6e72b355ac 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -2665,11 +2665,20 @@ export class StatChangePhase extends PokemonPhase { start() { const pokemon = this.getPokemon(); - if (!pokemon.isActive(true)) - return this.end(); + let random = false; const allStats = Utils.getEnumValues(BattleStat); - const filteredStats = this.stats.map(s => s !== BattleStat.RAND ? s : allStats[pokemon.randSeedInt(BattleStat.SPD + 1)]).filter(stat => { + if (this.stats.length === 1 && this.stats[0] === BattleStat.RAND) { + this.stats[0] = this.getRandomStat(); + random = true; + } + + this.aggregateStatChanges(random); + + if (!pokemon.isActive(true)) + return this.end(); + + const filteredStats = this.stats.map(s => s !== BattleStat.RAND ? s : this.getRandomStat()).filter(stat => { const cancelled = new Utils.BooleanHolder(false); if (!this.selfTarget && this.levels < 0) @@ -2750,11 +2759,62 @@ export class StatChangePhase extends PokemonPhase { end(); } + getRandomStat(): BattleStat { + const allStats = Utils.getEnumValues(BattleStat); + return allStats[this.getPokemon().randSeedInt(BattleStat.SPD + 1)]; + } + + aggregateStatChanges(random: boolean = false): void { + const isAccEva = [ BattleStat.ACC, BattleStat.EVA ].some(s => this.stats.includes(s)); + let existingPhase: StatChangePhase; + if (this.stats.length === 1) { + while ((existingPhase = (this.scene.findPhase(p => p instanceof StatChangePhase && p.battlerIndex === this.battlerIndex && p.stats.length === 1 + && (p.stats[0] === this.stats[0] || (random && p.stats[0] === BattleStat.RAND)) + && p.selfTarget === this.selfTarget && p.showMessage === this.showMessage && p.ignoreAbilities === this.ignoreAbilities) as StatChangePhase))) { + if (existingPhase.stats[0] === BattleStat.RAND) { + existingPhase.stats[0] = this.getRandomStat(); + if (existingPhase.stats[0] !== this.stats[0]) + continue; + } + this.levels += existingPhase.levels; + + if (!this.scene.tryRemovePhase(p => p === existingPhase)) + break; + } + } + while ((existingPhase = (this.scene.findPhase(p => p instanceof StatChangePhase && p.battlerIndex === this.battlerIndex && p.selfTarget === this.selfTarget + && ([ BattleStat.ACC, BattleStat.EVA ].some(s => p.stats.includes(s)) === isAccEva) + && p.levels === this.levels && p.showMessage === this.showMessage && p.ignoreAbilities === this.ignoreAbilities) as StatChangePhase))) { + this.stats.push(...existingPhase.stats); + if (!this.scene.tryRemovePhase(p => p === existingPhase)) + break; + } + } + getStatChangeMessages(stats: BattleStat[], levels: integer, relLevels: integer[]): string[] { const messages: string[] = []; - - for (let s = 0; s < stats.length; s++) - messages.push(getPokemonMessage(this.getPokemon(), `'s ${getBattleStatName(stats[s])} ${getBattleStatLevelChangeDescription(Math.abs(relLevels[s]), levels >= 1)}!`)); + + const relLevelStatIndexes = {}; + for (let rl = 0; rl < relLevels.length; rl++) { + const relLevel = relLevels[rl]; + if (!relLevelStatIndexes[relLevel]) + relLevelStatIndexes[relLevel] = []; + relLevelStatIndexes[relLevel].push(rl); + } + + Object.keys(relLevelStatIndexes).forEach(rl => { + const relLevelStats = stats.filter((_, i) => relLevelStatIndexes[rl].includes(i)); + let statsFragment = ''; + + if (relLevelStats.length > 1) { + statsFragment = relLevelStats.length >= 5 + ? 'stats' + : `${relLevelStats.slice(0, -1).map(s => getBattleStatName(s)).join(', ')}, and ${getBattleStatName(relLevelStats[relLevelStats.length - 1])}`; + } else + statsFragment = getBattleStatName(relLevelStats[0]); + messages.push(getPokemonMessage(this.getPokemon(), `'s ${statsFragment} ${getBattleStatLevelChangeDescription(Math.abs(parseInt(rl)), levels >= 1)}!`)); + }); + return messages; } } From 6066d2e47ec87505066fcc54e8fa7e4f95ea197b Mon Sep 17 00:00:00 2001 From: arColm Date: Tue, 23 Apr 2024 17:42:45 -0400 Subject: [PATCH 09/30] Implement Flying Press --- src/data/move.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/data/move.ts b/src/data/move.ts index 48714d00c07..53244082bd3 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -2301,6 +2301,14 @@ export class WaterSuperEffectTypeMultiplierAttr extends VariableMoveTypeMultipli } } +export class FlyingTypeMultiplierAttr extends VariableMoveTypeMultiplierAttr { + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const multiplier = args[0] as Utils.NumberHolder; + multiplier.value *= target.getAttackTypeEffectiveness(Type.FLYING); + return true; + } +} + export class OneHitKOAccuracyAttr extends VariableAccuracyAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const accuracy = args[0] as Utils.NumberHolder; @@ -5204,7 +5212,8 @@ export function initMoves() { .makesContact(false) .partial(), new AttackMove(Moves.FLYING_PRESS, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 95, 10, -1, 0, 6) - .partial(), + .attr(FlyingTypeMultiplierAttr) + .condition(failOnGravityCondition), new StatusMove(Moves.MAT_BLOCK, Type.FIGHTING, -1, 10, -1, 0, 6) .unimplemented(), new AttackMove(Moves.BELCH, Type.POISON, MoveCategory.SPECIAL, 120, 90, 10, -1, 0, 6) From ea40bd18f5289cb877ecad2e178b58ca0a3edfec Mon Sep 17 00:00:00 2001 From: John Martin Date: Wed, 24 Apr 2024 00:28:48 -0400 Subject: [PATCH 10/30] Minor text corrections to item descriptions. (#255) * Minor text corrections to item descriptions. * Update modifier-type.ts; minor text correction updates * Update modifier-type.ts; further text re-corrections. --- src/modifier/modifier-type.ts | 48 +++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 5baefffa8af..354f80f91fe 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -190,7 +190,7 @@ export class PokemonHpRestoreModifierType extends PokemonModifierType { protected healStatus: boolean; constructor(name: string, restorePoints: integer, restorePercent: integer, healStatus: boolean = false, newModifierFunc?: NewModifierFunc, selectFilter?: PokemonSelectFilter, iconImage?: string, group?: string) { - super(name, restorePoints ? `Restore ${restorePoints} HP or ${restorePercent}% HP for one Pokémon, whichever is higher` : `Fully restores HP for one Pokémon${healStatus ? ' and heals any status ailment ' : ''}`, + super(name, restorePoints ? `Restores ${restorePoints} HP or ${restorePercent}% HP for one Pokémon, whichever is higher` : `Fully restores HP for one Pokémon${healStatus ? ' and heals any status ailment' : ''}`, newModifierFunc || ((_type, args) => new Modifiers.PokemonHpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints, this.restorePercent, this.healStatus, false)), selectFilter || ((pokemon: PlayerPokemon) => { if (!pokemon.hp || (pokemon.hp >= pokemon.getMaxHp() && (!this.healStatus || !pokemon.status))) @@ -213,7 +213,7 @@ export class PokemonReviveModifierType extends PokemonHpRestoreModifierType { return null; }), iconImage, 'revive'); - this.description = `Revive one Pokémon and restore ${restorePercent}% HP`; + this.description = `Revive one Pokémon and restore ${restorePercent}% HP.`; this.selectFilter = (pokemon: PlayerPokemon) => { if (pokemon.hp) return PartyUiHandler.NoEffectMessage; @@ -224,7 +224,7 @@ export class PokemonReviveModifierType extends PokemonHpRestoreModifierType { export class PokemonStatusHealModifierType extends PokemonModifierType { constructor(name: string) { - super(name, `Heal any status ailment for one Pokémon`, + super(name, `Heal any status ailment for one Pokémon.`, ((_type, args) => new Modifiers.PokemonStatusHealModifier(this, (args[0] as PlayerPokemon).id)), ((pokemon: PlayerPokemon) => { if (!pokemon.hp || !pokemon.status) @@ -249,7 +249,7 @@ export class PokemonPpRestoreModifierType extends PokemonMoveModifierType { protected restorePoints: integer; constructor(name: string, restorePoints: integer, iconImage?: string) { - super(name, `Restore ${restorePoints > -1 ? restorePoints : 'all'} PP for one Pokémon move`, (_type, args) => new Modifiers.PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints), + super(name, `Restores ${restorePoints > -1 ? restorePoints : 'all'} PP for one Pokémon move`, (_type, args) => new Modifiers.PokemonPpRestoreModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.restorePoints), (_pokemon: PlayerPokemon) => { return null; }, (pokemonMove: PokemonMove) => { @@ -266,7 +266,7 @@ export class PokemonAllMovePpRestoreModifierType extends PokemonModifierType { protected restorePoints: integer; constructor(name: string, restorePoints: integer, iconImage?: string) { - super(name, `Restore ${restorePoints > -1 ? restorePoints : 'all'} PP for all of one Pokémon's moves`, (_type, args) => new Modifiers.PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints), + super(name, `Restores ${restorePoints > -1 ? restorePoints : 'all'} PP for all of one Pokémon's moves`, (_type, args) => new Modifiers.PokemonAllMovePpRestoreModifier(this, (args[0] as PlayerPokemon).id, this.restorePoints), (pokemon: PlayerPokemon) => { if (!pokemon.getMoveset().filter(m => m.ppUsed).length) return PartyUiHandler.NoEffectMessage; @@ -281,7 +281,7 @@ export class PokemonPpUpModifierType extends PokemonMoveModifierType { protected upPoints: integer; constructor(name: string, upPoints: integer, iconImage?: string) { - super(name, `Permanently increase PP for one Pokémon move by ${upPoints} for every 5 maximum PP (maximum 3)`, (_type, args) => new Modifiers.PokemonPpUpModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.upPoints), + super(name, `Permanently increases PP for one Pokémon move by ${upPoints} for every 5 maximum PP (maximum 3)`, (_type, args) => new Modifiers.PokemonPpUpModifier(this, (args[0] as PlayerPokemon).id, (args[1] as integer), this.upPoints), (_pokemon: PlayerPokemon) => { return null; }, (pokemonMove: PokemonMove) => { @@ -425,14 +425,14 @@ export class AttackTypeBoosterModifierType extends PokemonHeldItemModifierType i export class PokemonLevelIncrementModifierType extends PokemonModifierType { constructor(name: string, iconImage?: string) { - super(name, `Increase a Pokémon\'s level by 1`, (_type, args) => new Modifiers.PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id), + super(name, `Increases a Pokémon\'s level by 1`, (_type, args) => new Modifiers.PokemonLevelIncrementModifier(this, (args[0] as PlayerPokemon).id), (_pokemon: PlayerPokemon) => null, iconImage); } } export class AllPokemonLevelIncrementModifierType extends ModifierType { constructor(name: string, iconImage?: string) { - super(name, `Increase all party members' level by 1`, (_type, _args) => new Modifiers.PokemonLevelIncrementModifier(this, -1), iconImage); + super(name, `Increases all party members' level by 1`, (_type, _args) => new Modifiers.PokemonLevelIncrementModifier(this, -1), iconImage); } } @@ -469,7 +469,7 @@ export class PokemonBaseStatBoosterModifierType extends PokemonHeldItemModifierT class AllPokemonFullHpRestoreModifierType extends ModifierType { constructor(name: string, description?: string, newModifierFunc?: NewModifierFunc, iconImage?: string) { - super(name, description || `Restore 100% HP for all Pokémon`, newModifierFunc || ((_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, false)), iconImage); + super(name, description || `Restores 100% HP for all Pokémon`, newModifierFunc || ((_type, _args) => new Modifiers.PokemonHpRestoreModifier(this, -1, 0, 100, false)), iconImage); } } @@ -514,13 +514,13 @@ export class PokemonFriendshipBoosterModifierType extends PokemonHeldItemModifie export class PokemonMoveAccuracyBoosterModifierType extends PokemonHeldItemModifierType { constructor(name: string, amount: integer, iconImage?: string, group?: string, soundName?: string) { - super(name, `Increases move accuracy by ${amount} (up to 100)`, (_type, args) => new Modifiers.PokemonMoveAccuracyBoosterModifier(this, (args[0] as Pokemon).id, amount), iconImage, group, soundName); + super(name, `Increases move accuracy by ${amount} (maximum 100)`, (_type, args) => new Modifiers.PokemonMoveAccuracyBoosterModifier(this, (args[0] as Pokemon).id, amount), iconImage, group, soundName); } } export class PokemonMultiHitModifierType extends PokemonHeldItemModifierType { constructor(name: string, iconImage?: string) { - super(name, `Attacks hit one additional time at the cost of a 60/75/82.5% power reduction per stack respectively`, (type, args) => new Modifiers.PokemonMultiHitModifier(type as PokemonMultiHitModifierType, (args[0] as Pokemon).id), iconImage); + super(name, `Attacks hit one additional time at the cost of a 60/75/82.5% power reduction per stack respectively.`, (type, args) => new Modifiers.PokemonMultiHitModifier(type as PokemonMultiHitModifierType, (args[0] as Pokemon).id), iconImage); } } @@ -586,7 +586,7 @@ export class FormChangeItemModifierType extends PokemonModifierType implements G export class FusePokemonModifierType extends PokemonModifierType { constructor(name: string, iconImage?: string) { - super(name, 'Combines two Pokémon (transfers ability, splits base stats and types, shares move pool)', (_type, args) => new Modifiers.FusePokemonModifier(this, (args[0] as PlayerPokemon).id, (args[1] as PlayerPokemon).id), + super(name, 'Combines two Pokémon (transfers Ability, splits base stats and types, shares move pool)', (_type, args) => new Modifiers.FusePokemonModifier(this, (args[0] as PlayerPokemon).id, (args[1] as PlayerPokemon).id), (pokemon: PlayerPokemon) => { if (pokemon.isFusion()) return PartyUiHandler.NoEffectMessage; @@ -716,13 +716,13 @@ export class TerastallizeModifierType extends PokemonHeldItemModifierType implem export class ContactHeldItemTransferChanceModifierType extends PokemonHeldItemModifierType { constructor(name: string, chancePercent: integer, iconImage?: string, group?: string, soundName?: string) { - super(name, `Upon attacking, there is a ${chancePercent}% chance the foe's held item will be stolen`, (type, args) => new Modifiers.ContactHeldItemTransferChanceModifier(type, (args[0] as Pokemon).id, chancePercent), iconImage, group, soundName); + super(name, `Upon attacking, there is a ${chancePercent}% chance the foe's held item will be stolen.`, (type, args) => new Modifiers.ContactHeldItemTransferChanceModifier(type, (args[0] as Pokemon).id, chancePercent), iconImage, group, soundName); } } export class TurnHeldItemTransferModifierType extends PokemonHeldItemModifierType { constructor(name: string, iconImage?: string, group?: string, soundName?: string) { - super(name, 'Every turn, the holder acquires one held item from the foe', (type, args) => new Modifiers.TurnHeldItemTransferModifier(type, (args[0] as Pokemon).id), iconImage, group, soundName); + super(name, 'Every turn, the holder acquires one held item from the foe.', (type, args) => new Modifiers.TurnHeldItemTransferModifier(type, (args[0] as Pokemon).id), iconImage, group, soundName); } } @@ -772,9 +772,9 @@ export const modifierTypes = { RARE_EVOLUTION_ITEM: () => new EvolutionItemModifierTypeGenerator(true), FORM_CHANGE_ITEM: () => new FormChangeItemModifierTypeGenerator(), - MEGA_BRACELET: () => new ModifierType('Mega Bracelet', 'Mega stones become available', (type, _args) => new Modifiers.MegaEvolutionAccessModifier(type)), - DYNAMAX_BAND: () => new ModifierType('Dynamax Band', 'Max Mushrooms become available', (type, _args) => new Modifiers.GigantamaxAccessModifier(type)), - TERA_ORB: () => new ModifierType('Tera Orb', 'Tera Shards become available', (type, _args) => new Modifiers.TerastallizeAccessModifier(type)), + MEGA_BRACELET: () => new ModifierType('Mega Bracelet', 'Mega Stones become available.', (type, _args) => new Modifiers.MegaEvolutionAccessModifier(type)), + DYNAMAX_BAND: () => new ModifierType('Dynamax Band', 'Max Mushrooms become available.', (type, _args) => new Modifiers.GigantamaxAccessModifier(type)), + TERA_ORB: () => new ModifierType('Tera Orb', 'Tera Shards become available.', (type, _args) => new Modifiers.TerastallizeAccessModifier(type)), MAP: () => new ModifierType('Map', 'Allows you to choose your destination at a crossroads', (type, _args) => new Modifiers.MapModifier(type)), @@ -873,12 +873,12 @@ export const modifierTypes = { MEMORY_MUSHROOM: () => new RememberMoveModifierType('Memory Mushroom', 'Recall one Pokémon\'s forgotten move', 'big_mushroom'), - EXP_SHARE: () => new ModifierType('EXP. All', 'Non-participants receive 20% of a single participant\'s EXP. Points', + EXP_SHARE: () => new ModifierType('EXP. All', 'Non-participants receive 20% of a single participant\'s EXP. Points.', (type, _args) => new Modifiers.ExpShareModifier(type), 'exp_share'), - EXP_BALANCE: () => new ModifierType('EXP. Balance', 'Weighs EXP. Points received from battles towards lower leveled party members', + EXP_BALANCE: () => new ModifierType('EXP. Balance', 'Weighs EXP. Points received from battles towards lower-leveled party members', (type, _args) => new Modifiers.ExpBalanceModifier(type)), - OVAL_CHARM: () => new ModifierType('Oval Charm', 'When multiple Pokémon participate in a battle, each gets an extra 10% of the total EXP', + OVAL_CHARM: () => new ModifierType('Oval Charm', 'When multiple Pokémon participate in a battle, each gets an extra 10% of the total EXP.', (type, _args) => new Modifiers.MultipleParticipantExpBonusModifier(type)), EXP_CHARM: () => new ExpBoosterModifierType('EXP. Charm', 25), @@ -898,7 +898,7 @@ export const modifierTypes = { AMULET_COIN: () => new ModifierType('Amulet Coin', 'Increases money rewards by 20%', (type, _args) => new Modifiers.MoneyMultiplierModifier(type)), GOLDEN_PUNCH: () => new PokemonHeldItemModifierType('Golden Punch', 'Grants 50% of damage inflicted as money', (type, args) => new Modifiers.DamageMoneyRewardModifier(type, (args[0] as Pokemon).id)), - COIN_CASE: () => new ModifierType('Coin Case', 'After every 10th battle, receive 10% of your money in interest', (type, _args) => new Modifiers.MoneyInterestModifier(type)), + COIN_CASE: () => new ModifierType('Coin Case', 'After every 10th battle, receive 10% of your money in interest.', (type, _args) => new Modifiers.MoneyInterestModifier(type)), LOCK_CAPSULE: () => new ModifierType('Lock Capsule', 'Allows you to lock item rarities when rerolling items', (type, _args) => new Modifiers.LockModifierTiersModifier(type), 'lock_capsule'), @@ -907,7 +907,7 @@ export const modifierTypes = { MULTI_LENS: () => new PokemonMultiHitModifierType('Multi Lens', 'zoom_lens'), - HEALING_CHARM: () => new ModifierType('Healing Charm', 'Increases the effectiveness of HP restoring moves and items by 10% (excludes revives)', + HEALING_CHARM: () => new ModifierType('Healing Charm', 'Increases the effectiveness of HP restoring moves and items by 10% (excludes Revives)', (type, _args) => new Modifiers.HealingBoosterModifier(type, 1.1), 'healing_charm'), CANDY_JAR: () => new ModifierType('Candy Jar', 'Increases the number of levels added by Rare Candy items by 1', (type, _args) => new Modifiers.LevelIncrementBoosterModifier(type)), @@ -928,8 +928,8 @@ export const modifierTypes = { BATON: () => new PokemonHeldItemModifierType('Baton', 'Allows passing along effects when switching Pokémon, which also bypasses traps', (type, args) => new Modifiers.SwitchEffectTransferModifier(type, (args[0] as Pokemon).id), 'stick'), - SHINY_CHARM: () => new ModifierType('Shiny Charm', 'Dramatically increases the chance of a wild Pokémon being shiny', (type, _args) => new Modifiers.ShinyRateBoosterModifier(type)), - ABILITY_CHARM: () => new ModifierType('Ability Charm', 'Dramatically increases the chance of a wild Pokémon having a hidden ability', (type, _args) => new Modifiers.HiddenAbilityRateBoosterModifier(type)), + SHINY_CHARM: () => new ModifierType('Shiny Charm', 'Dramatically increases the chance of a wild Pokémon being Shiny', (type, _args) => new Modifiers.ShinyRateBoosterModifier(type)), + ABILITY_CHARM: () => new ModifierType('Ability Charm', 'Dramatically increases the chance of a wild Pokémon having a Hidden Ability', (type, _args) => new Modifiers.HiddenAbilityRateBoosterModifier(type)), IV_SCANNER: () => new ModifierType('IV Scanner', 'Allows scanning the IVs of wild Pokémon. 2 IVs are revealed per stack. The best IVs are shown first.', (type, _args) => new Modifiers.IvScannerModifier(type), 'scanner'), From 1b1578d266724627a26b2cc8c5bf309a6a1ecb21 Mon Sep 17 00:00:00 2001 From: Juan-Lucas Date: Wed, 24 Apr 2024 06:36:07 +0200 Subject: [PATCH 11/30] command-ui: add i18n for command ui handler and add i18n for fr (#258) * command-ui: add i18n for command ui handler and add i18n for fr * Add missing Spanish file * Add additional missing localization references --------- Co-authored-by: Flashfyre --- src/locales/en/command-ui-handler.ts | 9 + src/locales/es/command-ui-handler.ts | 9 + src/locales/es/pokemon.ts | 1086 ++++++++++++++++++++++++++ src/locales/fr/command-ui-handler.ts | 9 + src/plugins/i18n.ts | 19 +- src/ui/command-ui-handler.ts | 10 +- 6 files changed, 1136 insertions(+), 6 deletions(-) create mode 100644 src/locales/en/command-ui-handler.ts create mode 100644 src/locales/es/command-ui-handler.ts create mode 100644 src/locales/es/pokemon.ts create mode 100644 src/locales/fr/command-ui-handler.ts diff --git a/src/locales/en/command-ui-handler.ts b/src/locales/en/command-ui-handler.ts new file mode 100644 index 00000000000..889c1378b08 --- /dev/null +++ b/src/locales/en/command-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const commandUiHandler: SimpleTranslationEntries = { + "fight": "Fight", + "ball": "Ball", + "pokemon": "Pokémon", + "run": "Run", + "actionMessage": "What will\n{{pokemonName}} do?", +} as const; \ No newline at end of file diff --git a/src/locales/es/command-ui-handler.ts b/src/locales/es/command-ui-handler.ts new file mode 100644 index 00000000000..889c1378b08 --- /dev/null +++ b/src/locales/es/command-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const commandUiHandler: SimpleTranslationEntries = { + "fight": "Fight", + "ball": "Ball", + "pokemon": "Pokémon", + "run": "Run", + "actionMessage": "What will\n{{pokemonName}} do?", +} as const; \ No newline at end of file diff --git a/src/locales/es/pokemon.ts b/src/locales/es/pokemon.ts new file mode 100644 index 00000000000..09be8894eb4 --- /dev/null +++ b/src/locales/es/pokemon.ts @@ -0,0 +1,1086 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const pokemon: SimpleTranslationEntries = { + "bulbasaur": "Bulbasaur", + "ivysaur": "Ivysaur", + "venusaur": "Venusaur", + "charmander": "Charmander", + "charmeleon": "Charmeleon", + "charizard": "Charizard", + "squirtle": "Squirtle", + "wartortle": "Wartortle", + "blastoise": "Blastoise", + "caterpie": "Caterpie", + "metapod": "Metapod", + "butterfree": "Butterfree", + "weedle": "Weedle", + "kakuna": "Kakuna", + "beedrill": "Beedrill", + "pidgey": "Pidgey", + "pidgeotto": "Pidgeotto", + "pidgeot": "Pidgeot", + "rattata": "Rattata", + "raticate": "Raticate", + "spearow": "Spearow", + "fearow": "Fearow", + "ekans": "Ekans", + "arbok": "Arbok", + "pikachu": "Pikachu", + "raichu": "Raichu", + "sandshrew": "Sandshrew", + "sandslash": "Sandslash", + "nidoran_f": "Nidoran♀", + "nidorina": "Nidorina", + "nidoqueen": "Nidoqueen", + "nidoran_m": "Nidoran♂", + "nidorino": "Nidorino", + "nidoking": "Nidoking", + "clefairy": "Clefairy", + "clefable": "Clefable", + "vulpix": "Vulpix", + "ninetales": "Ninetales", + "jigglypuff": "Jigglypuff", + "wigglytuff": "Wigglytuff", + "zubat": "Zubat", + "golbat": "Golbat", + "oddish": "Oddish", + "gloom": "Gloom", + "vileplume": "Vileplume", + "paras": "Paras", + "parasect": "Parasect", + "venonat": "Venonat", + "venomoth": "Venomoth", + "diglett": "Diglett", + "dugtrio": "Dugtrio", + "meowth": "Meowth", + "persian": "Persian", + "psyduck": "Psyduck", + "golduck": "Golduck", + "mankey": "Mankey", + "primeape": "Primeape", + "growlithe": "Growlithe", + "arcanine": "Arcanine", + "poliwag": "Poliwag", + "poliwhirl": "Poliwhirl", + "poliwrath": "Poliwrath", + "abra": "Abra", + "kadabra": "Kadabra", + "alakazam": "Alakazam", + "machop": "Machop", + "machoke": "Machoke", + "machamp": "Machamp", + "bellsprout": "Bellsprout", + "weepinbell": "Weepinbell", + "victreebel": "Victreebel", + "tentacool": "Tentacool", + "tentacruel": "Tentacruel", + "geodude": "Geodude", + "graveler": "Graveler", + "golem": "Golem", + "ponyta": "Ponyta", + "rapidash": "Rapidash", + "slowpoke": "Slowpoke", + "slowbro": "Slowbro", + "magnemite": "Magnemite", + "magneton": "Magneton", + "farfetchd": "Farfetch'd", + "doduo": "Doduo", + "dodrio": "Dodrio", + "seel": "Seel", + "dewgong": "Dewgong", + "grimer": "Grimer", + "muk": "Muk", + "shellder": "Shellder", + "cloyster": "Cloyster", + "gastly": "Gastly", + "haunter": "Haunter", + "gengar": "Gengar", + "onix": "Onix", + "drowzee": "Drowzee", + "hypno": "Hypno", + "krabby": "Krabby", + "kingler": "Kingler", + "voltorb": "Voltorb", + "electrode": "Electrode", + "exeggcute": "Exeggcute", + "exeggutor": "Exeggutor", + "cubone": "Cubone", + "marowak": "Marowak", + "hitmonlee": "Hitmonlee", + "hitmonchan": "Hitmonchan", + "lickitung": "Lickitung", + "koffing": "Koffing", + "weezing": "Weezing", + "rhyhorn": "Rhyhorn", + "rhydon": "Rhydon", + "chansey": "Chansey", + "tangela": "Tangela", + "kangaskhan": "Kangaskhan", + "horsea": "Horsea", + "seadra": "Seadra", + "goldeen": "Goldeen", + "seaking": "Seaking", + "staryu": "Staryu", + "starmie": "Starmie", + "mr_mime": "Mr. Mime", + "scyther": "Scyther", + "jynx": "Jynx", + "electabuzz": "Electabuzz", + "magmar": "Magmar", + "pinsir": "Pinsir", + "tauros": "Tauros", + "magikarp": "Magikarp", + "gyarados": "Gyarados", + "lapras": "Lapras", + "ditto": "Ditto", + "eevee": "Eevee", + "vaporeon": "Vaporeon", + "jolteon": "Jolteon", + "flareon": "Flareon", + "porygon": "Porygon", + "omanyte": "Omanyte", + "omastar": "Omastar", + "kabuto": "Kabuto", + "kabutops": "Kabutops", + "aerodactyl": "Aerodactyl", + "snorlax": "Snorlax", + "articuno": "Articuno", + "zapdos": "Zapdos", + "moltres": "Moltres", + "dratini": "Dratini", + "dragonair": "Dragonair", + "dragonite": "Dragonite", + "mewtwo": "Mewtwo", + "mew": "Mew", + "chikorita": "Chikorita", + "bayleef": "Bayleef", + "meganium": "Meganium", + "cyndaquil": "Cyndaquil", + "quilava": "Quilava", + "typhlosion": "Typhlosion", + "totodile": "Totodile", + "croconaw": "Croconaw", + "feraligatr": "Feraligatr", + "sentret": "Sentret", + "furret": "Furret", + "hoothoot": "Hoothoot", + "noctowl": "Noctowl", + "ledyba": "Ledyba", + "ledian": "Ledian", + "spinarak": "Spinarak", + "ariados": "Ariados", + "crobat": "Crobat", + "chinchou": "Chinchou", + "lanturn": "Lanturn", + "pichu": "Pichu", + "cleffa": "Cleffa", + "igglybuff": "Igglybuff", + "togepi": "Togepi", + "togetic": "Togetic", + "natu": "Natu", + "xatu": "Xatu", + "mareep": "Mareep", + "flaaffy": "Flaaffy", + "ampharos": "Ampharos", + "bellossom": "Bellossom", + "marill": "Marill", + "azumarill": "Azumarill", + "sudowoodo": "Sudowoodo", + "politoed": "Politoed", + "hoppip": "Hoppip", + "skiploom": "Skiploom", + "jumpluff": "Jumpluff", + "aipom": "Aipom", + "sunkern": "Sunkern", + "sunflora": "Sunflora", + "yanma": "Yanma", + "wooper": "Wooper", + "quagsire": "Quagsire", + "espeon": "Espeon", + "umbreon": "Umbreon", + "murkrow": "Murkrow", + "slowking": "Slowking", + "misdreavus": "Misdreavus", + "unown": "Unown", + "wobbuffet": "Wobbuffet", + "girafarig": "Girafarig", + "pineco": "Pineco", + "forretress": "Forretress", + "dunsparce": "Dunsparce", + "gligar": "Gligar", + "steelix": "Steelix", + "snubbull": "Snubbull", + "granbull": "Granbull", + "qwilfish": "Qwilfish", + "scizor": "Scizor", + "shuckle": "Shuckle", + "heracross": "Heracross", + "sneasel": "Sneasel", + "teddiursa": "Teddiursa", + "ursaring": "Ursaring", + "slugma": "Slugma", + "magcargo": "Magcargo", + "swinub": "Swinub", + "piloswine": "Piloswine", + "corsola": "Corsola", + "remoraid": "Remoraid", + "octillery": "Octillery", + "delibird": "Delibird", + "mantine": "Mantine", + "skarmory": "Skarmory", + "houndour": "Houndour", + "houndoom": "Houndoom", + "kingdra": "Kingdra", + "phanpy": "Phanpy", + "donphan": "Donphan", + "porygon2": "Porygon2", + "stantler": "Stantler", + "smeargle": "Smeargle", + "tyrogue": "Tyrogue", + "hitmontop": "Hitmontop", + "smoochum": "Smoochum", + "elekid": "Elekid", + "magby": "Magby", + "miltank": "Miltank", + "blissey": "Blissey", + "raikou": "Raikou", + "entei": "Entei", + "suicune": "Suicune", + "larvitar": "Larvitar", + "pupitar": "Pupitar", + "tyranitar": "Tyranitar", + "lugia": "Lugia", + "ho_oh": "Ho-Oh", + "celebi": "Celebi", + "treecko": "Treecko", + "grovyle": "Grovyle", + "sceptile": "Sceptile", + "torchic": "Torchic", + "combusken": "Combusken", + "blaziken": "Blaziken", + "mudkip": "Mudkip", + "marshtomp": "Marshtomp", + "swampert": "Swampert", + "poochyena": "Poochyena", + "mightyena": "Mightyena", + "zigzagoon": "Zigzagoon", + "linoone": "Linoone", + "wurmple": "Wurmple", + "silcoon": "Silcoon", + "beautifly": "Beautifly", + "cascoon": "Cascoon", + "dustox": "Dustox", + "lotad": "Lotad", + "lombre": "Lombre", + "ludicolo": "Ludicolo", + "seedot": "Seedot", + "nuzleaf": "Nuzleaf", + "shiftry": "Shiftry", + "taillow": "Taillow", + "swellow": "Swellow", + "wingull": "Wingull", + "pelipper": "Pelipper", + "ralts": "Ralts", + "kirlia": "Kirlia", + "gardevoir": "Gardevoir", + "surskit": "Surskit", + "masquerain": "Masquerain", + "shroomish": "Shroomish", + "breloom": "Breloom", + "slakoth": "Slakoth", + "vigoroth": "Vigoroth", + "slaking": "Slaking", + "nincada": "Nincada", + "ninjask": "Ninjask", + "shedinja": "Shedinja", + "whismur": "Whismur", + "loudred": "Loudred", + "exploud": "Exploud", + "makuhita": "Makuhita", + "hariyama": "Hariyama", + "azurill": "Azurill", + "nosepass": "Nosepass", + "skitty": "Skitty", + "delcatty": "Delcatty", + "sableye": "Sableye", + "mawile": "Mawile", + "aron": "Aron", + "lairon": "Lairon", + "aggron": "Aggron", + "meditite": "Meditite", + "medicham": "Medicham", + "electrike": "Electrike", + "manectric": "Manectric", + "plusle": "Plusle", + "minun": "Minun", + "volbeat": "Volbeat", + "illumise": "Illumise", + "roselia": "Roselia", + "gulpin": "Gulpin", + "swalot": "Swalot", + "carvanha": "Carvanha", + "sharpedo": "Sharpedo", + "wailmer": "Wailmer", + "wailord": "Wailord", + "numel": "Numel", + "camerupt": "Camerupt", + "torkoal": "Torkoal", + "spoink": "Spoink", + "grumpig": "Grumpig", + "spinda": "Spinda", + "trapinch": "Trapinch", + "vibrava": "Vibrava", + "flygon": "Flygon", + "cacnea": "Cacnea", + "cacturne": "Cacturne", + "swablu": "Swablu", + "altaria": "Altaria", + "zangoose": "Zangoose", + "seviper": "Seviper", + "lunatone": "Lunatone", + "solrock": "Solrock", + "barboach": "Barboach", + "whiscash": "Whiscash", + "corphish": "Corphish", + "crawdaunt": "Crawdaunt", + "baltoy": "Baltoy", + "claydol": "Claydol", + "lileep": "Lileep", + "cradily": "Cradily", + "anorith": "Anorith", + "armaldo": "Armaldo", + "feebas": "Feebas", + "milotic": "Milotic", + "castform": "Castform", + "kecleon": "Kecleon", + "shuppet": "Shuppet", + "banette": "Banette", + "duskull": "Duskull", + "dusclops": "Dusclops", + "tropius": "Tropius", + "chimecho": "Chimecho", + "absol": "Absol", + "wynaut": "Wynaut", + "snorunt": "Snorunt", + "glalie": "Glalie", + "spheal": "Spheal", + "sealeo": "Sealeo", + "walrein": "Walrein", + "clamperl": "Clamperl", + "huntail": "Huntail", + "gorebyss": "Gorebyss", + "relicanth": "Relicanth", + "luvdisc": "Luvdisc", + "bagon": "Bagon", + "shelgon": "Shelgon", + "salamence": "Salamence", + "beldum": "Beldum", + "metang": "Metang", + "metagross": "Metagross", + "regirock": "Regirock", + "regice": "Regice", + "registeel": "Registeel", + "latias": "Latias", + "latios": "Latios", + "kyogre": "Kyogre", + "groudon": "Groudon", + "rayquaza": "Rayquaza", + "jirachi": "Jirachi", + "deoxys": "Deoxys", + "turtwig": "Turtwig", + "grotle": "Grotle", + "torterra": "Torterra", + "chimchar": "Chimchar", + "monferno": "Monferno", + "infernape": "Infernape", + "piplup": "Piplup", + "prinplup": "Prinplup", + "empoleon": "Empoleon", + "starly": "Starly", + "staravia": "Staravia", + "staraptor": "Staraptor", + "bidoof": "Bidoof", + "bibarel": "Bibarel", + "kricketot": "Kricketot", + "kricketune": "Kricketune", + "shinx": "Shinx", + "luxio": "Luxio", + "luxray": "Luxray", + "budew": "Budew", + "roserade": "Roserade", + "cranidos": "Cranidos", + "rampardos": "Rampardos", + "shieldon": "Shieldon", + "bastiodon": "Bastiodon", + "burmy": "Burmy", + "wormadam": "Wormadam", + "mothim": "Mothim", + "combee": "Combee", + "vespiquen": "Vespiquen", + "pachirisu": "Pachirisu", + "buizel": "Buizel", + "floatzel": "Floatzel", + "cherubi": "Cherubi", + "cherrim": "Cherrim", + "shellos": "Shellos", + "gastrodon": "Gastrodon", + "ambipom": "Ambipom", + "drifloon": "Drifloon", + "drifblim": "Drifblim", + "buneary": "Buneary", + "lopunny": "Lopunny", + "mismagius": "Mismagius", + "honchkrow": "Honchkrow", + "glameow": "Glameow", + "purugly": "Purugly", + "chingling": "Chingling", + "stunky": "Stunky", + "skuntank": "Skuntank", + "bronzor": "Bronzor", + "bronzong": "Bronzong", + "bonsly": "Bonsly", + "mime_jr": "Mime Jr.", + "happiny": "Happiny", + "chatot": "Chatot", + "spiritomb": "Spiritomb", + "gible": "Gible", + "gabite": "Gabite", + "garchomp": "Garchomp", + "munchlax": "Munchlax", + "riolu": "Riolu", + "lucario": "Lucario", + "hippopotas": "Hippopotas", + "hippowdon": "Hippowdon", + "skorupi": "Skorupi", + "drapion": "Drapion", + "croagunk": "Croagunk", + "toxicroak": "Toxicroak", + "carnivine": "Carnivine", + "finneon": "Finneon", + "lumineon": "Lumineon", + "mantyke": "Mantyke", + "snover": "Snover", + "abomasnow": "Abomasnow", + "weavile": "Weavile", + "magnezone": "Magnezone", + "lickilicky": "Lickilicky", + "rhyperior": "Rhyperior", + "tangrowth": "Tangrowth", + "electivire": "Electivire", + "magmortar": "Magmortar", + "togekiss": "Togekiss", + "yanmega": "Yanmega", + "leafeon": "Leafeon", + "glaceon": "Glaceon", + "gliscor": "Gliscor", + "mamoswine": "Mamoswine", + "porygon_z": "Porygon-Z", + "gallade": "Gallade", + "probopass": "Probopass", + "dusknoir": "Dusknoir", + "froslass": "Froslass", + "rotom": "Rotom", + "uxie": "Uxie", + "mesprit": "Mesprit", + "azelf": "Azelf", + "dialga": "Dialga", + "palkia": "Palkia", + "heatran": "Heatran", + "regigigas": "Regigigas", + "giratina": "Giratina", + "cresselia": "Cresselia", + "phione": "Phione", + "manaphy": "Manaphy", + "darkrai": "Darkrai", + "shaymin": "Shaymin", + "arceus": "Arceus", + "victini": "Victini", + "snivy": "Snivy", + "servine": "Servine", + "serperior": "Serperior", + "tepig": "Tepig", + "pignite": "Pignite", + "emboar": "Emboar", + "oshawott": "Oshawott", + "dewott": "Dewott", + "samurott": "Samurott", + "patrat": "Patrat", + "watchog": "Watchog", + "lillipup": "Lillipup", + "herdier": "Herdier", + "stoutland": "Stoutland", + "purrloin": "Purrloin", + "liepard": "Liepard", + "pansage": "Pansage", + "simisage": "Simisage", + "pansear": "Pansear", + "simisear": "Simisear", + "panpour": "Panpour", + "simipour": "Simipour", + "munna": "Munna", + "musharna": "Musharna", + "pidove": "Pidove", + "tranquill": "Tranquill", + "unfezant": "Unfezant", + "blitzle": "Blitzle", + "zebstrika": "Zebstrika", + "roggenrola": "Roggenrola", + "boldore": "Boldore", + "gigalith": "Gigalith", + "woobat": "Woobat", + "swoobat": "Swoobat", + "drilbur": "Drilbur", + "excadrill": "Excadrill", + "audino": "Audino", + "timburr": "Timburr", + "gurdurr": "Gurdurr", + "conkeldurr": "Conkeldurr", + "tympole": "Tympole", + "palpitoad": "Palpitoad", + "seismitoad": "Seismitoad", + "throh": "Throh", + "sawk": "Sawk", + "sewaddle": "Sewaddle", + "swadloon": "Swadloon", + "leavanny": "Leavanny", + "venipede": "Venipede", + "whirlipede": "Whirlipede", + "scolipede": "Scolipede", + "cottonee": "Cottonee", + "whimsicott": "Whimsicott", + "petilil": "Petilil", + "lilligant": "Lilligant", + "basculin": "Basculin", + "sandile": "Sandile", + "krokorok": "Krokorok", + "krookodile": "Krookodile", + "darumaka": "Darumaka", + "darmanitan": "Darmanitan", + "maractus": "Maractus", + "dwebble": "Dwebble", + "crustle": "Crustle", + "scraggy": "Scraggy", + "scrafty": "Scrafty", + "sigilyph": "Sigilyph", + "yamask": "Yamask", + "cofagrigus": "Cofagrigus", + "tirtouga": "Tirtouga", + "carracosta": "Carracosta", + "archen": "Archen", + "archeops": "Archeops", + "trubbish": "Trubbish", + "garbodor": "Garbodor", + "zorua": "Zorua", + "zoroark": "Zoroark", + "minccino": "Minccino", + "cinccino": "Cinccino", + "gothita": "Gothita", + "gothorita": "Gothorita", + "gothitelle": "Gothitelle", + "solosis": "Solosis", + "duosion": "Duosion", + "reuniclus": "Reuniclus", + "ducklett": "Ducklett", + "swanna": "Swanna", + "vanillite": "Vanillite", + "vanillish": "Vanillish", + "vanilluxe": "Vanilluxe", + "deerling": "Deerling", + "sawsbuck": "Sawsbuck", + "emolga": "Emolga", + "karrablast": "Karrablast", + "escavalier": "Escavalier", + "foongus": "Foongus", + "amoonguss": "Amoonguss", + "frillish": "Frillish", + "jellicent": "Jellicent", + "alomomola": "Alomomola", + "joltik": "Joltik", + "galvantula": "Galvantula", + "ferroseed": "Ferroseed", + "ferrothorn": "Ferrothorn", + "klink": "Klink", + "klang": "Klang", + "klinklang": "Klinklang", + "tynamo": "Tynamo", + "eelektrik": "Eelektrik", + "eelektross": "Eelektross", + "elgyem": "Elgyem", + "beheeyem": "Beheeyem", + "litwick": "Litwick", + "lampent": "Lampent", + "chandelure": "Chandelure", + "axew": "Axew", + "fraxure": "Fraxure", + "haxorus": "Haxorus", + "cubchoo": "Cubchoo", + "beartic": "Beartic", + "cryogonal": "Cryogonal", + "shelmet": "Shelmet", + "accelgor": "Accelgor", + "stunfisk": "Stunfisk", + "mienfoo": "Mienfoo", + "mienshao": "Mienshao", + "druddigon": "Druddigon", + "golett": "Golett", + "golurk": "Golurk", + "pawniard": "Pawniard", + "bisharp": "Bisharp", + "bouffalant": "Bouffalant", + "rufflet": "Rufflet", + "braviary": "Braviary", + "vullaby": "Vullaby", + "mandibuzz": "Mandibuzz", + "heatmor": "Heatmor", + "durant": "Durant", + "deino": "Deino", + "zweilous": "Zweilous", + "hydreigon": "Hydreigon", + "larvesta": "Larvesta", + "volcarona": "Volcarona", + "cobalion": "Cobalion", + "terrakion": "Terrakion", + "virizion": "Virizion", + "tornadus": "Tornadus", + "thundurus": "Thundurus", + "reshiram": "Reshiram", + "zekrom": "Zekrom", + "landorus": "Landorus", + "kyurem": "Kyurem", + "keldeo": "Keldeo", + "meloetta": "Meloetta", + "genesect": "Genesect", + "chespin": "Chespin", + "quilladin": "Quilladin", + "chesnaught": "Chesnaught", + "fennekin": "Fennekin", + "braixen": "Braixen", + "delphox": "Delphox", + "froakie": "Froakie", + "frogadier": "Frogadier", + "greninja": "Greninja", + "bunnelby": "Bunnelby", + "diggersby": "Diggersby", + "fletchling": "Fletchling", + "fletchinder": "Fletchinder", + "talonflame": "Talonflame", + "scatterbug": "Scatterbug", + "spewpa": "Spewpa", + "vivillon": "Vivillon", + "litleo": "Litleo", + "pyroar": "Pyroar", + "flabebe": "Flabébé", + "floette": "Floette", + "florges": "Florges", + "skiddo": "Skiddo", + "gogoat": "Gogoat", + "pancham": "Pancham", + "pangoro": "Pangoro", + "furfrou": "Furfrou", + "espurr": "Espurr", + "meowstic": "Meowstic", + "honedge": "Honedge", + "doublade": "Doublade", + "aegislash": "Aegislash", + "spritzee": "Spritzee", + "aromatisse": "Aromatisse", + "swirlix": "Swirlix", + "slurpuff": "Slurpuff", + "inkay": "Inkay", + "malamar": "Malamar", + "binacle": "Binacle", + "barbaracle": "Barbaracle", + "skrelp": "Skrelp", + "dragalge": "Dragalge", + "clauncher": "Clauncher", + "clawitzer": "Clawitzer", + "helioptile": "Helioptile", + "heliolisk": "Heliolisk", + "tyrunt": "Tyrunt", + "tyrantrum": "Tyrantrum", + "amaura": "Amaura", + "aurorus": "Aurorus", + "sylveon": "Sylveon", + "hawlucha": "Hawlucha", + "dedenne": "Dedenne", + "carbink": "Carbink", + "goomy": "Goomy", + "sliggoo": "Sliggoo", + "goodra": "Goodra", + "klefki": "Klefki", + "phantump": "Phantump", + "trevenant": "Trevenant", + "pumpkaboo": "Pumpkaboo", + "gourgeist": "Gourgeist", + "bergmite": "Bergmite", + "avalugg": "Avalugg", + "noibat": "Noibat", + "noivern": "Noivern", + "xerneas": "Xerneas", + "yveltal": "Yveltal", + "zygarde": "Zygarde", + "diancie": "Diancie", + "hoopa": "Hoopa", + "volcanion": "Volcanion", + "rowlet": "Rowlet", + "dartrix": "Dartrix", + "decidueye": "Decidueye", + "litten": "Litten", + "torracat": "Torracat", + "incineroar": "Incineroar", + "popplio": "Popplio", + "brionne": "Brionne", + "primarina": "Primarina", + "pikipek": "Pikipek", + "trumbeak": "Trumbeak", + "toucannon": "Toucannon", + "yungoos": "Yungoos", + "gumshoos": "Gumshoos", + "grubbin": "Grubbin", + "charjabug": "Charjabug", + "vikavolt": "Vikavolt", + "crabrawler": "Crabrawler", + "crabominable": "Crabominable", + "oricorio": "Oricorio", + "cutiefly": "Cutiefly", + "ribombee": "Ribombee", + "rockruff": "Rockruff", + "lycanroc": "Lycanroc", + "wishiwashi": "Wishiwashi", + "mareanie": "Mareanie", + "toxapex": "Toxapex", + "mudbray": "Mudbray", + "mudsdale": "Mudsdale", + "dewpider": "Dewpider", + "araquanid": "Araquanid", + "fomantis": "Fomantis", + "lurantis": "Lurantis", + "morelull": "Morelull", + "shiinotic": "Shiinotic", + "salandit": "Salandit", + "salazzle": "Salazzle", + "stufful": "Stufful", + "bewear": "Bewear", + "bounsweet": "Bounsweet", + "steenee": "Steenee", + "tsareena": "Tsareena", + "comfey": "Comfey", + "oranguru": "Oranguru", + "passimian": "Passimian", + "wimpod": "Wimpod", + "golisopod": "Golisopod", + "sandygast": "Sandygast", + "palossand": "Palossand", + "pyukumuku": "Pyukumuku", + "type_null": "Type: Null", + "silvally": "Silvally", + "minior": "Minior", + "komala": "Komala", + "turtonator": "Turtonator", + "togedemaru": "Togedemaru", + "mimikyu": "Mimikyu", + "bruxish": "Bruxish", + "drampa": "Drampa", + "dhelmise": "Dhelmise", + "jangmo_o": "Jangmo-o", + "hakamo_o": "Hakamo-o", + "kommo_o": "Kommo-o", + "tapu_koko": "Tapu Koko", + "tapu_lele": "Tapu Lele", + "tapu_bulu": "Tapu Bulu", + "tapu_fini": "Tapu Fini", + "cosmog": "Cosmog", + "cosmoem": "Cosmoem", + "solgaleo": "Solgaleo", + "lunala": "Lunala", + "nihilego": "Nihilego", + "buzzwole": "Buzzwole", + "pheromosa": "Pheromosa", + "xurkitree": "Xurkitree", + "celesteela": "Celesteela", + "kartana": "Kartana", + "guzzlord": "Guzzlord", + "necrozma": "Necrozma", + "magearna": "Magearna", + "marshadow": "Marshadow", + "poipole": "Poipole", + "naganadel": "Naganadel", + "stakataka": "Stakataka", + "blacephalon": "Blacephalon", + "zeraora": "Zeraora", + "meltan": "Meltan", + "melmetal": "Melmetal", + "grookey": "Grookey", + "thwackey": "Thwackey", + "rillaboom": "Rillaboom", + "scorbunny": "Scorbunny", + "raboot": "Raboot", + "cinderace": "Cinderace", + "sobble": "Sobble", + "drizzile": "Drizzile", + "inteleon": "Inteleon", + "skwovet": "Skwovet", + "greedent": "Greedent", + "rookidee": "Rookidee", + "corvisquire": "Corvisquire", + "corviknight": "Corviknight", + "blipbug": "Blipbug", + "dottler": "Dottler", + "orbeetle": "Orbeetle", + "nickit": "Nickit", + "thievul": "Thievul", + "gossifleur": "Gossifleur", + "eldegoss": "Eldegoss", + "wooloo": "Wooloo", + "dubwool": "Dubwool", + "chewtle": "Chewtle", + "drednaw": "Drednaw", + "yamper": "Yamper", + "boltund": "Boltund", + "rolycoly": "Rolycoly", + "carkol": "Carkol", + "coalossal": "Coalossal", + "applin": "Applin", + "flapple": "Flapple", + "appletun": "Appletun", + "silicobra": "Silicobra", + "sandaconda": "Sandaconda", + "cramorant": "Cramorant", + "arrokuda": "Arrokuda", + "barraskewda": "Barraskewda", + "toxel": "Toxel", + "toxtricity": "Toxtricity", + "sizzlipede": "Sizzlipede", + "centiskorch": "Centiskorch", + "clobbopus": "Clobbopus", + "grapploct": "Grapploct", + "sinistea": "Sinistea", + "polteageist": "Polteageist", + "hatenna": "Hatenna", + "hattrem": "Hattrem", + "hatterene": "Hatterene", + "impidimp": "Impidimp", + "morgrem": "Morgrem", + "grimmsnarl": "Grimmsnarl", + "obstagoon": "Obstagoon", + "perrserker": "Perrserker", + "cursola": "Cursola", + "sirfetchd": "Sirfetch'd", + "mr_rime": "Mr. Rime", + "runerigus": "Runerigus", + "milcery": "Milcery", + "alcremie": "Alcremie", + "falinks": "Falinks", + "pincurchin": "Pincurchin", + "snom": "Snom", + "frosmoth": "Frosmoth", + "stonjourner": "Stonjourner", + "eiscue": "Eiscue", + "indeedee": "Indeedee", + "morpeko": "Morpeko", + "cufant": "Cufant", + "copperajah": "Copperajah", + "dracozolt": "Dracozolt", + "arctozolt": "Arctozolt", + "dracovish": "Dracovish", + "arctovish": "Arctovish", + "duraludon": "Duraludon", + "dreepy": "Dreepy", + "drakloak": "Drakloak", + "dragapult": "Dragapult", + "zacian": "Zacian", + "zamazenta": "Zamazenta", + "eternatus": "Eternatus", + "kubfu": "Kubfu", + "urshifu": "Urshifu", + "zarude": "Zarude", + "regieleki": "Regieleki", + "regidrago": "Regidrago", + "glastrier": "Glastrier", + "spectrier": "Spectrier", + "calyrex": "Calyrex", + "wyrdeer": "Wyrdeer", + "kleavor": "Kleavor", + "ursaluna": "Ursaluna", + "basculegion": "Basculegion", + "sneasler": "Sneasler", + "overqwil": "Overqwil", + "enamorus": "Enamorus", + "sprigatito": "Sprigatito", + "floragato": "Floragato", + "meowscarada": "Meowscarada", + "fuecoco": "Fuecoco", + "crocalor": "Crocalor", + "skeledirge": "Skeledirge", + "quaxly": "Quaxly", + "quaxwell": "Quaxwell", + "quaquaval": "Quaquaval", + "lechonk": "Lechonk", + "oinkologne": "Oinkologne", + "tarountula": "Tarountula", + "spidops": "Spidops", + "nymble": "Nymble", + "lokix": "Lokix", + "pawmi": "Pawmi", + "pawmo": "Pawmo", + "pawmot": "Pawmot", + "tandemaus": "Tandemaus", + "maushold": "Maushold", + "fidough": "Fidough", + "dachsbun": "Dachsbun", + "smoliv": "Smoliv", + "dolliv": "Dolliv", + "arboliva": "Arboliva", + "squawkabilly": "Squawkabilly", + "nacli": "Nacli", + "naclstack": "Naclstack", + "garganacl": "Garganacl", + "charcadet": "Charcadet", + "armarouge": "Armarouge", + "ceruledge": "Ceruledge", + "tadbulb": "Tadbulb", + "bellibolt": "Bellibolt", + "wattrel": "Wattrel", + "kilowattrel": "Kilowattrel", + "maschiff": "Maschiff", + "mabosstiff": "Mabosstiff", + "shroodle": "Shroodle", + "grafaiai": "Grafaiai", + "bramblin": "Bramblin", + "brambleghast": "Brambleghast", + "toedscool": "Toedscool", + "toedscruel": "Toedscruel", + "klawf": "Klawf", + "capsakid": "Capsakid", + "scovillain": "Scovillain", + "rellor": "Rellor", + "rabsca": "Rabsca", + "flittle": "Flittle", + "espathra": "Espathra", + "tinkatink": "Tinkatink", + "tinkatuff": "Tinkatuff", + "tinkaton": "Tinkaton", + "wiglett": "Wiglett", + "wugtrio": "Wugtrio", + "bombirdier": "Bombirdier", + "finizen": "Finizen", + "palafin": "Palafin", + "varoom": "Varoom", + "revavroom": "Revavroom", + "cyclizar": "Cyclizar", + "orthworm": "Orthworm", + "glimmet": "Glimmet", + "glimmora": "Glimmora", + "greavard": "Greavard", + "houndstone": "Houndstone", + "flamigo": "Flamigo", + "cetoddle": "Cetoddle", + "cetitan": "Cetitan", + "veluza": "Veluza", + "dondozo": "Dondozo", + "tatsugiri": "Tatsugiri", + "annihilape": "Annihilape", + "clodsire": "Clodsire", + "farigiraf": "Farigiraf", + "dudunsparce": "Dudunsparce", + "kingambit": "Kingambit", + "great_tusk": "Great Tusk", + "scream_tail": "Scream Tail", + "brute_bonnet": "Brute Bonnet", + "flutter_mane": "Flutter Mane", + "slither_wing": "Slither Wing", + "sandy_shocks": "Sandy Shocks", + "iron_treads": "Iron Treads", + "iron_bundle": "Iron Bundle", + "iron_hands": "Iron Hands", + "iron_jugulis": "Iron Jugulis", + "iron_moth": "Iron Moth", + "iron_thorns": "Iron Thorns", + "frigibax": "Frigibax", + "arctibax": "Arctibax", + "baxcalibur": "Baxcalibur", + "gimmighoul": "Gimmighoul", + "gholdengo": "Gholdengo", + "wo_chien": "Wo-Chien", + "chien_pao": "Chien-Pao", + "ting_lu": "Ting-Lu", + "chi_yu": "Chi-Yu", + "roaring_moon": "Roaring Moon", + "iron_valiant": "Iron Valiant", + "koraidon": "Koraidon", + "miraidon": "Miraidon", + "walking_wake": "Walking Wake", + "iron_leaves": "Iron Leaves", + "dipplin": "Dipplin", + "poltchageist": "Poltchageist", + "sinistcha": "Sinistcha", + "okidogi": "Okidogi", + "munkidori": "Munkidori", + "fezandipiti": "Fezandipiti", + "ogerpon": "Ogerpon", + "archaludon": "Archaludon", + "hydrapple": "Hydrapple", + "gouging_fire": "Gouging Fire", + "raging_bolt": "Raging Bolt", + "iron_boulder": "Iron Boulder", + "iron_crown": "Iron Crown", + "terapagos": "Terapagos", + "pecharunt": "Pecharunt", + "alola_rattata": "Rattata", + "alola_raticate": "Raticate", + "alola_raichu": "Raichu", + "alola_sandshrew": "Sandshrew", + "alola_sandslash": "Sandslash", + "alola_vulpix": "Vulpix", + "alola_ninetales": "Ninetales", + "alola_diglett": "Diglett", + "alola_dugtrio": "Dugtrio", + "alola_meowth": "Meowth", + "alola_persian": "Persian", + "alola_geodude": "Geodude", + "alola_graveler": "Graveler", + "alola_golem": "Golem", + "alola_grimer": "Grimer", + "alola_muk": "Muk", + "alola_exeggutor": "Exeggutor", + "alola_marowak": "Marowak", + "eternal_floette": "Floette", + "galar_meowth": "Meowth", + "galar_ponyta": "Ponyta", + "galar_rapidash": "Rapidash", + "galar_slowpoke": "Slowpoke", + "galar_slowbro": "Slowbro", + "galar_farfetchd": "Farfetch'd", + "galar_weezing": "Weezing", + "galar_mr_mime": "Mr. Mime", + "galar_articuno": "Articuno", + "galar_zapdos": "Zapdos", + "galar_moltres": "Moltres", + "galar_slowking": "Slowking", + "galar_corsola": "Corsola", + "galar_zigzagoon": "Zigzagoon", + "galar_linoone": "Linoone", + "galar_darumaka": "Darumaka", + "galar_darmanitan": "Darmanitan", + "galar_yamask": "Yamask", + "galar_stunfisk": "Stunfisk", + "hisui_growlithe": "Growlithe", + "hisui_arcanine": "Arcanine", + "hisui_voltorb": "Voltorb", + "hisui_electrode": "Electrode", + "hisui_typhlosion": "Typhlosion", + "hisui_qwilfish": "Qwilfish", + "hisui_sneasel": "Sneasel", + "hisui_samurott": "Samurott", + "hisui_lilligant": "Lilligant", + "hisui_zorua": "Zorua", + "hisui_zoroark": "Zoroark", + "hisui_braviary": "Braviary", + "hisui_sliggoo": "Sliggoo", + "hisui_goodra": "Goodra", + "hisui_avalugg": "Avalugg", + "hisui_decidueye": "Decidueye", + "paldea_tauros": "Tauros", + "paldea_wooper": "Wooper", + "bloodmoon_ursaluna": "Ursaluna", +} as const; \ No newline at end of file diff --git a/src/locales/fr/command-ui-handler.ts b/src/locales/fr/command-ui-handler.ts new file mode 100644 index 00000000000..3df0ba58587 --- /dev/null +++ b/src/locales/fr/command-ui-handler.ts @@ -0,0 +1,9 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const commandUiHandler: SimpleTranslationEntries = { + "fight": "Attaque", + "ball": "Ball", + "pokemon": "Pokémon", + "run": "Fuite", + "actionMessage": "Que doit faire\n{{pokemonName}}?", +} as const; \ No newline at end of file diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 65565dc8eda..23a7a8e1d7d 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -13,12 +13,18 @@ import { pokeball as esPokeball } from '../locales/es/pokeball'; import { pokeball as frPokeball } from '../locales/fr/pokeball'; import { pokemon as enPokemon } from '../locales/en/pokemon'; +import { pokemon as esPokemon } from '../locales/es/pokemon'; import { pokemon as frPokemon } from '../locales/fr/pokemon'; +import { commandUiHandler as enCommandUiHandler } from '../locales/en/command-ui-handler'; +import { commandUiHandler as esCommandUiHandler } from '../locales/es/command-ui-handler'; +import { commandUiHandler as frCommandUiHandler } from '../locales/fr/command-ui-handler'; + export interface SimpleTranslationEntries { [key: string]: string } + export interface MoveTranslationEntry { name: string, effect: string @@ -65,21 +71,25 @@ export function initI18n(): void { move: enMove, pokeball: enPokeball, pokemon: enPokemon, + commandUiHandler: enCommandUiHandler, }, es: { menu: esMenu, move: esMove, pokeball: esPokeball, - }, - it: { - menu: itMenu, + pokemon: esPokemon, + commandUiHandler: esCommandUiHandler, }, fr: { menu: frMenu, move: frMove, pokeball: frPokeball, pokemon: frPokemon, - } + commandUiHandler: frCommandUiHandler, + }, + it: { + menu: itMenu, + }, }, }); } @@ -92,6 +102,7 @@ declare module 'i18next' { move: typeof enMove; pokeball: typeof enPokeball; pokemon: typeof enPokemon; + commandUiHandler: typeof enCommandUiHandler; }; } } diff --git a/src/ui/command-ui-handler.ts b/src/ui/command-ui-handler.ts index c0fdd43fa84..b8223694b4c 100644 --- a/src/ui/command-ui-handler.ts +++ b/src/ui/command-ui-handler.ts @@ -4,6 +4,7 @@ import { addTextObject, TextStyle } from "./text"; import PartyUiHandler, { PartyUiMode } from "./party-ui-handler"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; +import i18next from '../plugins/i18n'; export enum Command { FIGHT = 0, @@ -25,7 +26,12 @@ export default class CommandUiHandler extends UiHandler { setup() { const ui = this.getUi(); - const commands = [ 'Fight', 'Ball', 'Pokémon', 'Run' ]; + const commands = [ + i18next.t('commandUiHandler:fight'), + i18next.t('commandUiHandler:ball'), + i18next.t('commandUiHandler:pokemon'), + i18next.t('commandUiHandler:run') + ]; this.commandsContainer = this.scene.add.container(216, -38.7); this.commandsContainer.setVisible(false); @@ -55,7 +61,7 @@ export default class CommandUiHandler extends UiHandler { messageHandler.commandWindow.setVisible(true); messageHandler.movesWindowContainer.setVisible(false); messageHandler.message.setWordWrapWidth(1110); - messageHandler.showText(`What will\n${commandPhase.getPokemon().name} do?`, 0); + messageHandler.showText(i18next.t('commandUiHandler:actionMessage', {pokemonName: commandPhase.getPokemon().name}), 0); this.setCursor(this.getCursor()); return true; From adc383a8f99cb61e32c8140ec1ffc9eac2e33354 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 24 Apr 2024 01:51:30 -0400 Subject: [PATCH 12/30] Add UI support for 2 additional save slots --- src/ui/save-slot-select-ui-handler.ts | 52 +++++++++++++++++++++------ 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/src/ui/save-slot-select-ui-handler.ts b/src/ui/save-slot-select-ui-handler.ts index 21865045141..181b0643cb9 100644 --- a/src/ui/save-slot-select-ui-handler.ts +++ b/src/ui/save-slot-select-ui-handler.ts @@ -7,10 +7,9 @@ import { addWindow } from "./ui-theme"; import * as Utils from "../utils"; import PokemonData from "../system/pokemon-data"; import { PokemonHeldItemModifier } from "../modifier/modifier"; -import { TitlePhase } from "../phases"; import MessageUiHandler from "./message-ui-handler"; -const sessionSlotCount = 3; +const sessionSlotCount = 5; export enum SaveSlotUiMode { LOAD, @@ -30,8 +29,12 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { private uiMode: SaveSlotUiMode; private saveSlotSelectCallback: SaveSlotSelectCallback; + private scrollCursor: integer = 0; + private cursorObj: Phaser.GameObjects.NineSlice; + private sessionSlotsContainerInitialY: number; + constructor(scene: BattleScene) { super(scene, Mode.SAVE_SLOT); } @@ -47,7 +50,9 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { loadSessionBg.setOrigin(0, 0); this.saveSlotSelectContainer.add(loadSessionBg); - this.sessionSlotsContainer = this.scene.add.container(8, -this.scene.game.canvas.height / 6 + 8); + this.sessionSlotsContainerInitialY = -this.scene.game.canvas.height / 6 + 8; + + this.sessionSlotsContainer = this.scene.add.container(8, this.sessionSlotsContainerInitialY); this.saveSlotSelectContainer.add(this.sessionSlotsContainer); this.saveSlotSelectMessageBoxContainer = this.scene.add.container(0, 0); @@ -76,6 +81,7 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { this.saveSlotSelectContainer.setVisible(true); this.populateSessionSlots(); + this.setScrollCursor(0); this.setCursor(0); return true; @@ -90,13 +96,14 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { if (button === Button.ACTION || button === Button.CANCEL) { const originalCallback = this.saveSlotSelectCallback; if (button === Button.ACTION) { - if (this.uiMode === SaveSlotUiMode.LOAD && !this.sessionSlots[this.cursor].hasData) + const cursor = this.cursor + this.scrollCursor; + if (this.uiMode === SaveSlotUiMode.LOAD && !this.sessionSlots[cursor].hasData) error = true; else { switch (this.uiMode) { case SaveSlotUiMode.LOAD: this.saveSlotSelectCallback = null; - originalCallback(this.cursor); + originalCallback(cursor); break; case SaveSlotUiMode.SAVE: const saveAndCallback = () => { @@ -105,16 +112,16 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { ui.revertMode(); ui.showText(null, 0); ui.setMode(Mode.MESSAGE); - originalCallback(this.cursor); + originalCallback(cursor); }; - if (this.sessionSlots[this.cursor].hasData) { + if (this.sessionSlots[cursor].hasData) { ui.showText('Overwrite the data in the selected slot?', null, () => { ui.setOverlayMode(Mode.CONFIRM, () => saveAndCallback(), () => { ui.revertMode(); ui.showText(null, 0); }, false, 0, 19, 2000); }); - } else if (this.sessionSlots[this.cursor].hasData === false) + } else if (this.sessionSlots[cursor].hasData === false) saveAndCallback(); else return false; @@ -130,10 +137,16 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { } else { switch (button) { case Button.UP: - success = this.setCursor(this.cursor ? this.cursor - 1 : 0); + if (this.cursor) + success = this.setCursor(this.cursor - 1); + else if (this.scrollCursor) + success = this.setScrollCursor(this.scrollCursor - 1); break; case Button.DOWN: - success = this.setCursor(this.cursor < sessionSlotCount - 1 ? this.cursor + 1 : 2); + if (this.cursor < 2) + success = this.setCursor(this.cursor + 1); + else if (this.scrollCursor < sessionSlotCount - 3) + success = this.setScrollCursor(this.scrollCursor + 1); break; } } @@ -178,7 +191,24 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { this.cursorObj.setOrigin(0, 0); this.sessionSlotsContainer.add(this.cursorObj); } - this.cursorObj.setPosition(4, 4 + cursor * 56); + this.cursorObj.setPosition(4, 4 + (cursor + this.scrollCursor) * 56); + + return changed; + } + + setScrollCursor(scrollCursor: integer): boolean { + let changed = scrollCursor !== this.scrollCursor; + + if (changed) { + this.scrollCursor = scrollCursor; + this.setCursor(this.cursor); + this.scene.tweens.add({ + targets: this.sessionSlotsContainer, + y: this.sessionSlotsContainerInitialY - 56 * scrollCursor, + duration: Utils.fixedInt(325), + ease: 'Sine.easeInOut' + }); + } return changed; } From 4ea67976b940b9da75794730ddf621346fbd5237 Mon Sep 17 00:00:00 2001 From: Edralo Date: Wed, 24 Apr 2024 13:45:44 +0200 Subject: [PATCH 13/30] Fix password input types for languages other than english --- src/ui/form-modal-ui-handler.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ui/form-modal-ui-handler.ts b/src/ui/form-modal-ui-handler.ts index 3e326322c17..ec5f4147c58 100644 --- a/src/ui/form-modal-ui-handler.ts +++ b/src/ui/form-modal-ui-handler.ts @@ -5,6 +5,7 @@ import { TextStyle, addTextInputObject, addTextObject } from "./text"; import { WindowVariant, addWindow } from "./ui-theme"; import InputText from "phaser3-rex-plugins/plugins/inputtext"; import * as Utils from "../utils"; +import i18next from '../plugins/i18n'; export interface FormModalConfig extends ModalConfig { errorMessage?: string; @@ -55,7 +56,7 @@ export abstract class FormModalUiHandler extends ModalUiHandler { const inputBg = addWindow(this.scene, 0, 0, 80, 16, false, false, 0, 0, WindowVariant.XTHIN); - const isPassword = field.includes('Password'); + const isPassword = field.includes(i18next.t("menu:password")) || field.includes(i18next.t("menu:confirmPassword")); const input = addTextInputObject(this.scene, 4, -2, 440, 116, TextStyle.TOOLTIP_CONTENT, { type: isPassword ? 'password' : 'text', maxLength: isPassword ? 64 : 16 }); input.setOrigin(0, 0); From cf3a7dca35cae5c818f3df360d53764f6e2c6a41 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 24 Apr 2024 09:26:46 -0400 Subject: [PATCH 14/30] Comment out variant data fix to prevent ability data corruption --- src/system/game-data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 3a3077fadc1..575701eb484 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -347,7 +347,7 @@ export class GameData { } else { if ([ '1.0.0', '1.0.1' ].includes(systemData.gameVersion)) this.migrateStarterAbilities(systemData); - this.fixVariantData(systemData); + //this.fixVariantData(systemData); this.fixStarterData(systemData); // Migrate ability starter data if empty for caught species Object.keys(systemData.starterData).forEach(sd => { From 69eec95960b9b5a35b3c46fcb76339e2a20cb85f Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 24 Apr 2024 12:56:56 -0400 Subject: [PATCH 15/30] Add missing female Bidoof line variants --- .../pokemon/variant/back/female/399_2.json | 2414 +++++++++++++++++ .../pokemon/variant/back/female/399_2.png | Bin 0 -> 6952 bytes .../pokemon/variant/back/female/400.json | 13 + public/images/pokemon/variant/female/399.json | 16 + public/images/pokemon/variant/female/400.json | 16 + 5 files changed, 2459 insertions(+) create mode 100644 public/images/pokemon/variant/back/female/399_2.json create mode 100644 public/images/pokemon/variant/back/female/399_2.png create mode 100644 public/images/pokemon/variant/back/female/400.json create mode 100644 public/images/pokemon/variant/female/399.json create mode 100644 public/images/pokemon/variant/female/400.json diff --git a/public/images/pokemon/variant/back/female/399_2.json b/public/images/pokemon/variant/back/female/399_2.json new file mode 100644 index 00000000000..c2e9b3f1735 --- /dev/null +++ b/public/images/pokemon/variant/back/female/399_2.json @@ -0,0 +1,2414 @@ +{ + "textures": [ + { + "image": "399_2.png", + "format": "RGBA8888", + "size": { + "w": 180, + "h": 180 + }, + "scale": 1, + "frames": [ + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 49, + "h": 37 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 37 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 49, + "h": 37 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 37 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 49, + "h": 37 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 37 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 49, + "h": 37 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 37 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 49, + "h": 37 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 37 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 49, + "h": 37 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 37 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 49, + "h": 37 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 37 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 49, + "h": 37 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 37 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 49, + "h": 37 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 37 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 8, + "w": 49, + "h": 37 + }, + "frame": { + "x": 0, + "y": 0, + "w": 49, + "h": 37 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0111.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0112.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0113.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0114.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 44, + "h": 39 + }, + "frame": { + "x": 49, + "y": 0, + "w": 44, + "h": 39 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 0, + "y": 4, + "w": 49, + "h": 40 + }, + "frame": { + "x": 93, + "y": 0, + "w": 49, + "h": 40 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 0, + "y": 4, + "w": 49, + "h": 40 + }, + "frame": { + "x": 93, + "y": 0, + "w": 49, + "h": 40 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 0, + "y": 4, + "w": 49, + "h": 40 + }, + "frame": { + "x": 93, + "y": 0, + "w": 49, + "h": 40 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 0, + "y": 4, + "w": 49, + "h": 40 + }, + "frame": { + "x": 93, + "y": 0, + "w": 49, + "h": 40 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 0, + "y": 4, + "w": 49, + "h": 40 + }, + "frame": { + "x": 93, + "y": 0, + "w": 49, + "h": 40 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 0, + "y": 4, + "w": 49, + "h": 40 + }, + "frame": { + "x": 93, + "y": 0, + "w": 49, + "h": 40 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 0, + "y": 4, + "w": 49, + "h": 40 + }, + "frame": { + "x": 93, + "y": 0, + "w": 49, + "h": 40 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 0, + "y": 4, + "w": 49, + "h": 40 + }, + "frame": { + "x": 93, + "y": 0, + "w": 49, + "h": 40 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 0, + "y": 4, + "w": 49, + "h": 40 + }, + "frame": { + "x": 93, + "y": 0, + "w": 49, + "h": 40 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 0, + "y": 4, + "w": 49, + "h": 40 + }, + "frame": { + "x": 93, + "y": 0, + "w": 49, + "h": 40 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 45, + "h": 40 + }, + "frame": { + "x": 0, + "y": 37, + "w": 45, + "h": 40 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 45, + "h": 40 + }, + "frame": { + "x": 0, + "y": 37, + "w": 45, + "h": 40 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 45, + "h": 40 + }, + "frame": { + "x": 0, + "y": 37, + "w": 45, + "h": 40 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 45, + "h": 40 + }, + "frame": { + "x": 0, + "y": 37, + "w": 45, + "h": 40 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 47, + "h": 40 + }, + "frame": { + "x": 45, + "y": 39, + "w": 47, + "h": 40 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 47, + "h": 40 + }, + "frame": { + "x": 45, + "y": 39, + "w": 47, + "h": 40 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 47, + "h": 40 + }, + "frame": { + "x": 45, + "y": 39, + "w": 47, + "h": 40 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 47, + "h": 40 + }, + "frame": { + "x": 45, + "y": 39, + "w": 47, + "h": 40 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 5, + "w": 44, + "h": 40 + }, + "frame": { + "x": 92, + "y": 40, + "w": 44, + "h": 40 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 5, + "w": 44, + "h": 40 + }, + "frame": { + "x": 92, + "y": 40, + "w": 44, + "h": 40 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 5, + "w": 44, + "h": 40 + }, + "frame": { + "x": 92, + "y": 40, + "w": 44, + "h": 40 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 5, + "w": 44, + "h": 40 + }, + "frame": { + "x": 92, + "y": 40, + "w": 44, + "h": 40 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 40, + "w": 44, + "h": 41 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 40, + "w": 44, + "h": 41 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 40, + "w": 44, + "h": 41 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 40, + "w": 44, + "h": 41 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 40, + "w": 44, + "h": 41 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 40, + "w": 44, + "h": 41 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 40, + "w": 44, + "h": 41 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 40, + "w": 44, + "h": 41 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 40, + "w": 44, + "h": 41 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 40, + "w": 44, + "h": 41 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 41 + }, + "frame": { + "x": 0, + "y": 77, + "w": 44, + "h": 41 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 41 + }, + "frame": { + "x": 0, + "y": 77, + "w": 44, + "h": 41 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 41 + }, + "frame": { + "x": 0, + "y": 77, + "w": 44, + "h": 41 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 41 + }, + "frame": { + "x": 0, + "y": 77, + "w": 44, + "h": 41 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 41 + }, + "frame": { + "x": 0, + "y": 77, + "w": 44, + "h": 41 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 41 + }, + "frame": { + "x": 0, + "y": 77, + "w": 44, + "h": 41 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 41 + }, + "frame": { + "x": 0, + "y": 77, + "w": 44, + "h": 41 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 41 + }, + "frame": { + "x": 0, + "y": 77, + "w": 44, + "h": 41 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 41 + }, + "frame": { + "x": 0, + "y": 77, + "w": 44, + "h": 41 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 44, + "h": 41 + }, + "frame": { + "x": 0, + "y": 77, + "w": 44, + "h": 41 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 46, + "h": 40 + }, + "frame": { + "x": 44, + "y": 79, + "w": 46, + "h": 40 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 46, + "h": 40 + }, + "frame": { + "x": 44, + "y": 79, + "w": 46, + "h": 40 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 46, + "h": 40 + }, + "frame": { + "x": 44, + "y": 79, + "w": 46, + "h": 40 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 46, + "h": 40 + }, + "frame": { + "x": 44, + "y": 79, + "w": 46, + "h": 40 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 46, + "h": 41 + }, + "frame": { + "x": 90, + "y": 80, + "w": 46, + "h": 41 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 46, + "h": 41 + }, + "frame": { + "x": 90, + "y": 80, + "w": 46, + "h": 41 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 46, + "h": 41 + }, + "frame": { + "x": 90, + "y": 80, + "w": 46, + "h": 41 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 46, + "h": 41 + }, + "frame": { + "x": 90, + "y": 80, + "w": 46, + "h": 41 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 46, + "h": 41 + }, + "frame": { + "x": 90, + "y": 80, + "w": 46, + "h": 41 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 46, + "h": 41 + }, + "frame": { + "x": 90, + "y": 80, + "w": 46, + "h": 41 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 46, + "h": 41 + }, + "frame": { + "x": 90, + "y": 80, + "w": 46, + "h": 41 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 46, + "h": 41 + }, + "frame": { + "x": 90, + "y": 80, + "w": 46, + "h": 41 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 46, + "h": 41 + }, + "frame": { + "x": 90, + "y": 80, + "w": 46, + "h": 41 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 46, + "h": 41 + }, + "frame": { + "x": 90, + "y": 80, + "w": 46, + "h": 41 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 81, + "w": 44, + "h": 41 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 81, + "w": 44, + "h": 41 + } + }, + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 81, + "w": 44, + "h": 41 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 4, + "w": 44, + "h": 41 + }, + "frame": { + "x": 136, + "y": 81, + "w": 44, + "h": 41 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 44, + "h": 42 + }, + "frame": { + "x": 0, + "y": 118, + "w": 44, + "h": 42 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 44, + "h": 42 + }, + "frame": { + "x": 0, + "y": 118, + "w": 44, + "h": 42 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 44, + "h": 42 + }, + "frame": { + "x": 0, + "y": 118, + "w": 44, + "h": 42 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 44, + "h": 42 + }, + "frame": { + "x": 0, + "y": 118, + "w": 44, + "h": 42 + } + }, + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 44, + "h": 42 + }, + "frame": { + "x": 0, + "y": 118, + "w": 44, + "h": 42 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 44, + "h": 42 + }, + "frame": { + "x": 0, + "y": 118, + "w": 44, + "h": 42 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 44, + "h": 42 + }, + "frame": { + "x": 0, + "y": 118, + "w": 44, + "h": 42 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 44, + "h": 42 + }, + "frame": { + "x": 0, + "y": 118, + "w": 44, + "h": 42 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 44, + "h": 42 + }, + "frame": { + "x": 0, + "y": 118, + "w": 44, + "h": 42 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 44, + "h": 42 + }, + "frame": { + "x": 0, + "y": 118, + "w": 44, + "h": 42 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 46, + "h": 41 + }, + "frame": { + "x": 44, + "y": 119, + "w": 46, + "h": 41 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 46, + "h": 41 + }, + "frame": { + "x": 44, + "y": 119, + "w": 46, + "h": 41 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 46, + "h": 41 + }, + "frame": { + "x": 44, + "y": 119, + "w": 46, + "h": 41 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 46, + "h": 41 + }, + "frame": { + "x": 44, + "y": 119, + "w": 46, + "h": 41 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 46, + "h": 42 + }, + "frame": { + "x": 90, + "y": 121, + "w": 46, + "h": 42 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 4, + "y": 3, + "w": 46, + "h": 42 + }, + "frame": { + "x": 90, + "y": 121, + "w": 46, + "h": 42 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 44, + "h": 42 + }, + "frame": { + "x": 136, + "y": 122, + "w": 44, + "h": 42 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 51, + "h": 45 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 44, + "h": 42 + }, + "frame": { + "x": 136, + "y": 122, + "w": 44, + "h": 42 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:166d6bff38ea8945fae5e64c1106413a:2aa7b9b68f399a27af5a5270b38116ce:7b55afdea5fe8b0745f3f525c240592c$" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/female/399_2.png b/public/images/pokemon/variant/back/female/399_2.png new file mode 100644 index 0000000000000000000000000000000000000000..fcd948a0ef94ebddb5a0fe90305401dabc92757e GIT binary patch literal 6952 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 Ee^?H_*#H0l literal 0 HcmV?d00001 diff --git a/public/images/pokemon/variant/back/female/400.json b/public/images/pokemon/variant/back/female/400.json new file mode 100644 index 00000000000..c7e831cae97 --- /dev/null +++ b/public/images/pokemon/variant/back/female/400.json @@ -0,0 +1,13 @@ +{ + "1": { + "ad947b": "bd9171", + "e6d69c": "fff5d1", + "5a3a31": "70323f", + "3a3129": "3a3129", + "bd844a": "dba0ac", + "8c5a31": "c46269", + "101010": "101010", + "423a31": "3e3040", + "63523a": "824561" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/female/399.json b/public/images/pokemon/variant/female/399.json new file mode 100644 index 00000000000..3eff691158a --- /dev/null +++ b/public/images/pokemon/variant/female/399.json @@ -0,0 +1,16 @@ +{ + "1": { + "423110": "423110", + "9c6331": "d46378", + "c58c42": "e5a5bb", + "634a31": "70323f", + "101010": "101010", + "cebd84": "eba978", + "ffefbd": "fff5d1", + "ffffff": "ffffff", + "5a4229": "824561", + "ef5a4a": "ffa488", + "cec5c5": "b7b9d0", + "848484": "848484" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/female/400.json b/public/images/pokemon/variant/female/400.json new file mode 100644 index 00000000000..616586d3539 --- /dev/null +++ b/public/images/pokemon/variant/female/400.json @@ -0,0 +1,16 @@ +{ + "1": { + "5a3a31": "5a3a31", + "bd844a": "dba0ac", + "101010": "101010", + "8c5a31": "c46269", + "e6d69c": "fff5d1", + "ad947b": "bd9171", + "c5c5b5": "b7b9d0", + "ffffff": "ffffff", + "3a3129": "3a3129", + "63523a": "824561", + "de4a4a": "ffa488", + "423a31": "3e3040" + } +} \ No newline at end of file From 4173f87a703db59f35c55e85d35d17442e5c6040 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Wed, 24 Apr 2024 11:58:37 -0500 Subject: [PATCH 16/30] Add easier method of evolving Mantyke There is now an alternate easier evolution method for Mantyke into Mantine, that being having Remoraid simply being registered as caught and be level 32. --- src/data/biomes.ts | 2 +- src/data/pokemon-evolutions.ts | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/data/biomes.ts b/src/data/biomes.ts index 4f5a4e5af64..d6e84bcbc7c 100644 --- a/src/data/biomes.ts +++ b/src/data/biomes.ts @@ -1844,7 +1844,7 @@ export const biomeTrainerPools: BiomeTrainerPools = { [BiomePoolTier.RARE]: [], [BiomePoolTier.SUPER_RARE]: [], [BiomePoolTier.ULTRA_RARE]: [], - [BiomePoolTier.BOSS]: [ TrainerType.BRAWLY, TrainerType.KORRINA, TrainerType.BEA, TrainerType.MAYLENE ], + [BiomePoolTier.BOSS]: [ TrainerType.BRAWLY, TrainerType.MAYLENE, TrainerType.KORRINA, TrainerType.BEA ], [BiomePoolTier.BOSS_RARE]: [], [BiomePoolTier.BOSS_SUPER_RARE]: [], [BiomePoolTier.BOSS_ULTRA_RARE]: [] diff --git a/src/data/pokemon-evolutions.ts b/src/data/pokemon-evolutions.ts index 68369389066..04e49f17dcf 100644 --- a/src/data/pokemon-evolutions.ts +++ b/src/data/pokemon-evolutions.ts @@ -625,6 +625,10 @@ export const pokemonEvolutions: PokemonEvolutions = { [Species.FINNEON]: [ new SpeciesEvolution(Species.LUMINEON, 31, null, null) ], + [Species.MANTYKE]: [ + new SpeciesEvolution(Species.MANTINE, 1, null, new SpeciesEvolutionCondition(p => !!p.scene.getParty().find(p => p.species.speciesId === Species.REMORAID)), SpeciesWildEvolutionDelay.MEDIUM), + new SpeciesEvolution(Species.MANTINE, 32, null, new SpeciesEvolutionCondition(p => !!p.scene.gameData.dexData[Species.REMORAID].caughtAttr), SpeciesWildEvolutionDelay.MEDIUM) + ], [Species.SNOVER]: [ new SpeciesEvolution(Species.ABOMASNOW, 40, null, null) ], @@ -1341,9 +1345,6 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.GALAR_MR_MIME, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.MIMIC).length > 0 && (p.scene.arena.biomeType === Biome.ICE_CAVE || p.scene.arena.biomeType === Biome.SNOWY_FOREST)), SpeciesWildEvolutionDelay.MEDIUM), new SpeciesEvolution(Species.MR_MIME, 1, null, new SpeciesEvolutionCondition(p => p.moveset.filter(m => m.moveId === Moves.MIMIC).length > 0), SpeciesWildEvolutionDelay.MEDIUM) ], - [Species.MANTYKE]: [ - new SpeciesEvolution(Species.MANTINE, 1, null, new SpeciesEvolutionCondition(p => !!p.scene.getParty().find(p => p.species.speciesId === Species.REMORAID)), SpeciesWildEvolutionDelay.MEDIUM) - ], [Species.PANSAGE]: [ new SpeciesEvolution(Species.SIMISAGE, 1, EvolutionItem.LEAF_STONE, null, SpeciesWildEvolutionDelay.LONG) ], From d88a177915a010ed292aa665f0f96263b6117747 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Wed, 24 Apr 2024 12:54:34 -0500 Subject: [PATCH 17/30] Fix crash with trainer Mantykes the first evolution method was causing a crash due to a conflict, so it was removed for now. --- src/data/pokemon-evolutions.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/data/pokemon-evolutions.ts b/src/data/pokemon-evolutions.ts index 04e49f17dcf..0c1dfe06ca1 100644 --- a/src/data/pokemon-evolutions.ts +++ b/src/data/pokemon-evolutions.ts @@ -626,7 +626,6 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(Species.LUMINEON, 31, null, null) ], [Species.MANTYKE]: [ - new SpeciesEvolution(Species.MANTINE, 1, null, new SpeciesEvolutionCondition(p => !!p.scene.getParty().find(p => p.species.speciesId === Species.REMORAID)), SpeciesWildEvolutionDelay.MEDIUM), new SpeciesEvolution(Species.MANTINE, 32, null, new SpeciesEvolutionCondition(p => !!p.scene.gameData.dexData[Species.REMORAID].caughtAttr), SpeciesWildEvolutionDelay.MEDIUM) ], [Species.SNOVER]: [ From 37266a7a5dfcaa533deedf10d117d0f85abeb266 Mon Sep 17 00:00:00 2001 From: Dakurei Date: Wed, 24 Apr 2024 20:38:46 +0200 Subject: [PATCH 18/30] Fixing typo (fr locales) + Add missing i18n (#270) * Fix typo * Missing usage of i18n --- src/locales/fr/command-ui-handler.ts | 2 +- src/locales/fr/menu.ts | 12 ++++++------ src/phases.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/locales/fr/command-ui-handler.ts b/src/locales/fr/command-ui-handler.ts index 3df0ba58587..1b3d01d2c4f 100644 --- a/src/locales/fr/command-ui-handler.ts +++ b/src/locales/fr/command-ui-handler.ts @@ -5,5 +5,5 @@ export const commandUiHandler: SimpleTranslationEntries = { "ball": "Ball", "pokemon": "Pokémon", "run": "Fuite", - "actionMessage": "Que doit faire\n{{pokemonName}}?", + "actionMessage": "Que doit faire\n{{pokemonName}} ?", } as const; \ No newline at end of file diff --git a/src/locales/fr/menu.ts b/src/locales/fr/menu.ts index c0ebb687110..b05e7e6940d 100644 --- a/src/locales/fr/menu.ts +++ b/src/locales/fr/menu.ts @@ -14,7 +14,7 @@ export const menu: SimpleTranslationEntries = { "register": "S'inscrire", "emptyUsername": "Le nom d'utilisateur est manquant", "invalidLoginUsername": "Le nom d'utilisateur n'est pas valide", - "invalidRegisterUsername": "Le nom d'utilisateur ne doit contenir que \ndes lettres, chiffres ou traits bas", + "invalidRegisterUsername": "Le nom d'utilisateur ne doit contenir que\ndes lettres, chiffres ou traits bas", "invalidLoginPassword": "Le mot de passe n'est pas valide", "invalidRegisterPassword": "Le mot de passe doit contenir 6 caractères ou plus", "usernameAlreadyUsed": "Le nom d'utilisateur est déjà utilisé", @@ -30,11 +30,11 @@ export const menu: SimpleTranslationEntries = { "boyOrGirl": "Es-tu un garçon ou une fille ?", "boy": "Garçon", "girl": "Fille", - "bossAppeared": "Un {{bossName}} est apparaît.", + "bossAppeared": "Un {{bossName}} apparaît.", "trainerAppeared": "Un combat est lancé\npar {{trainerName}} !", - "singleWildAppeared": "Un {{pokemonName}} sauvage apparaît!", + "singleWildAppeared": "Un {{pokemonName}} sauvage apparaît !", "multiWildAppeared": "Un {{pokemonName1}} et un {{pokemonName2}}\nsauvages apparaissent !", - "playerComeBack": "{{pokemonName}}, on change!\nReviens !", + "playerComeBack": "{{pokemonName}}, on change !\nReviens !", "trainerComeBack": "{{trainerName}} retire {{pokemonName}} !", "playerGo": "{{pokemonName}} ! Go !", "trainerGo": "{{pokemonName}} est envoyé par\n{{trainerName}} !", @@ -43,7 +43,7 @@ export const menu: SimpleTranslationEntries = { "sendOutPokemon": "{{pokemonName}} ! Go !", "levelCapUp": "La limite de niveau\na été augmentée à {{levelCap}} !", "moveNotImplemented": "{{moveName}} n'est pas encore implémenté et ne peut pas être sélectionné.", - "moveDisabled": "{{moveName}} est désactivé !", + "moveDisabled": "{{moveName}} est sous entrave !", "noPokeballForce": "Une force mystérieuse\nempêche l'utilisation des Poké Balls.", "noPokeballTrainer": "Le Dresseur détourne la Ball\nVoler, c'est mal !", "noPokeballMulti": "Impossible ! On ne peut pas viser\nquand il y a deux Pokémon!", @@ -53,5 +53,5 @@ export const menu: SimpleTranslationEntries = { "noEscapePokemon": "{{moveName}} de {{pokemonName}}\nempêche {{escapeVerb}} !", "escapeVerbSwitch": "le changement", "escapeVerbFlee": "la fuite", - "notDisabled": "{{moveName}} n'est plus désactivé !", + "notDisabled": "{{moveName}} n'est plus sous entrave !", } as const; \ No newline at end of file diff --git a/src/phases.ts b/src/phases.ts index e6e72b355ac..3b3d3e7d94c 100644 --- a/src/phases.ts +++ b/src/phases.ts @@ -1185,7 +1185,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { } if (this.player) { - this.scene.ui.showText(`Go! ${this.getPokemon().name}!`); + this.scene.ui.showText(i18next.t('menu:playerGo', {pokemonName: this.getPokemon().name})); if (this.player) this.scene.pbTray.hide(); this.scene.trainer.setTexture(`trainer_${this.scene.gameData.gender === PlayerGender.FEMALE ? 'f' : 'm'}_back_pb`); From 6b3442a26032c97a0d8f8ba88079166f052c9de9 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Wed, 24 Apr 2024 13:40:59 -0500 Subject: [PATCH 19/30] =?UTF-8?q?Update=20stone=20evolution=20Pok=C3=A9mon?= =?UTF-8?q?'s=20learnsets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moves that are relearned in the official games are now level 1 moves for these Pokémon, as they have paltry movesets otherwise. --- src/data/pokemon-level-moves.ts | 247 ++++++++++++++++++++++++-------- 1 file changed, 190 insertions(+), 57 deletions(-) diff --git a/src/data/pokemon-level-moves.ts b/src/data/pokemon-level-moves.ts index 51ddbb53d8a..10e57fcddb1 100644 --- a/src/data/pokemon-level-moves.ts +++ b/src/data/pokemon-level-moves.ts @@ -581,6 +581,23 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.METEOR_MASH ], [ 1, Moves.MOONBLAST ], [ 1, Moves.LIFE_DEW ], + [ 1, Moves.POUND ], + [ 1, Moves.GROWL ], + [ 1, Moves.SING ], + [ 1, Moves.DEFENSE_CURL ], + [ 1, Moves.SPLASH ], + [ 1, Moves.SWEET_KISS ], + [ 1, Moves.CHARM ], + [ 1, Moves.ENCORE ], + [ 1, Moves.MOONLIGHT ], + [ 1, Moves.FOLLOW_ME ], + [ 1, Moves.COSMIC_POWER ], + [ 1, Moves.GRAVITY ], + [ 1, Moves.HEALING_WISH ], + [ 1, Moves.COPYCAT ], + [ 1, Moves.AFTER_YOU ], + [ 1, Moves.STORED_POWER ], + [ 1, Moves.DISARMING_VOICE ], ], [Species.VULPIX]: [ [ 1, Moves.TAIL_WHIP ], @@ -600,9 +617,22 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 52, Moves.FIRE_BLAST ], ], [Species.NINETALES]: [ - [ 1, Moves.TAIL_WHIP ], [ 1, Moves.FLAMETHROWER ], + [ 1, Moves.TAIL_WHIP ], [ 1, Moves.QUICK_ATTACK ], + [ 1, Moves.DISABLE ], + [ 1, Moves.EMBER ], + [ 1, Moves.FIRE_SPIN ], + [ 1, Moves.CONFUSE_RAY ], + [ 1, Moves.FIRE_BLAST ], + [ 1, Moves.SPITE ], + [ 1, Moves.SAFEGUARD ], + [ 1, Moves.WILL_O_WISP ], + [ 1, Moves.IMPRISON ], + [ 1, Moves.EXTRASENSORY ], + [ 1, Moves.NASTY_PLOT ], + [ 1, Moves.INCINERATE ], + [ 1, Moves.INFERNO ], ], [Species.JIGGLYPUFF]: [ [ 1, Moves.POUND ], @@ -995,9 +1025,18 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.POLIWRATH]: [ [ 0, Moves.DYNAMIC_PUNCH ], - [ 1, Moves.BODY_SLAM ], [ 1, Moves.BUBBLE_BEAM ], + [ 1, Moves.BODY_SLAM ], [ 1, Moves.HYPNOSIS ], + [ 1, Moves.POUND ], + [ 1, Moves.DOUBLE_EDGE ], + [ 1, Moves.WATER_GUN ], + [ 1, Moves.HYDRO_PUMP ], + [ 1, Moves.BELLY_DRUM ], + [ 1, Moves.RAIN_DANCE ], + [ 1, Moves.MUD_SHOT ], + [ 1, Moves.EARTH_POWER ], + [ 1, Moves.CIRCLE_THROW ], ], [Species.ABRA]: [ [ 1, Moves.TELEPORT ], @@ -1121,9 +1160,14 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [Species.VICTREEBEL]: [ [ 0, Moves.LEAF_STORM ], [ 1, Moves.VINE_WHIP ], - [ 1, Moves.RAZOR_LEAF ], [ 1, Moves.SLEEP_POWDER ], [ 1, Moves.SWEET_SCENT ], + [ 1, Moves.RAZOR_LEAF ], + [ 1, Moves.STOCKPILE ], + [ 1, Moves.SWALLOW ], + [ 1, Moves.SPIT_UP ], + [ 1, Moves.GASTRO_ACID ], + [ 1, Moves.POWER_WHIP ], [ 44, Moves.LEAF_BLADE ], ], [Species.TENTACOOL]: [ @@ -1671,23 +1715,24 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.EXEGGUTOR]: [ [ 0, Moves.STOMP ], - [ 1, Moves.ABSORB ], + [ 1, Moves.SEED_BOMB ], + [ 1, Moves.PSYSHOCK ], + [ 1, Moves.WOOD_HAMMER ], + [ 1, Moves.LEAF_STORM ], [ 1, Moves.MEGA_DRAIN ], - [ 1, Moves.LEECH_SEED ], - [ 1, Moves.SOLAR_BEAM ], [ 1, Moves.CONFUSION ], + [ 1, Moves.SYNTHESIS ], + [ 1, Moves.BULLET_SEED ], + [ 1, Moves.GIGA_DRAIN ], + [ 1, Moves.EXTRASENSORY ], + [ 1, Moves.UPROAR ], + [ 1, Moves.WORRY_SEED ], + [ 1, Moves.SOLAR_BEAM ], + [ 1, Moves.ABSORB ], [ 1, Moves.HYPNOSIS ], [ 1, Moves.REFLECT ], - [ 1, Moves.GIGA_DRAIN ], - [ 1, Moves.SYNTHESIS ], - [ 1, Moves.UPROAR ], - [ 1, Moves.EXTRASENSORY ], - [ 1, Moves.BULLET_SEED ], - [ 1, Moves.WORRY_SEED ], - [ 1, Moves.SEED_BOMB ], - [ 1, Moves.LEAF_STORM ], - [ 1, Moves.WOOD_HAMMER ], - [ 1, Moves.PSYSHOCK ], + [ 1, Moves.LEECH_SEED ], + [ 1, Moves.GROWTH ], ], [Species.CUBONE]: [ [ 1, Moves.GROWL ], @@ -3107,10 +3152,20 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.POLITOED]: [ [ 0, Moves.BOUNCE ], - [ 1, Moves.POUND ], + [ 1, Moves.RAIN_DANCE ], [ 1, Moves.HYDRO_PUMP ], [ 1, Moves.BELLY_DRUM ], - [ 1, Moves.RAIN_DANCE ], + [ 1, Moves.POUND ], + [ 1, Moves.BODY_SLAM ], + [ 1, Moves.DOUBLE_EDGE ], + [ 1, Moves.WATER_GUN ], + [ 1, Moves.BUBBLE_BEAM ], + [ 1, Moves.HYPNOSIS ], + [ 1, Moves.PERISH_SONG ], + [ 1, Moves.SWAGGER ], + [ 1, Moves.HYPER_VOICE ], + [ 1, Moves.MUD_SHOT ], + [ 1, Moves.EARTH_POWER ], ], [Species.HOPPIP]: [ [ 1, Moves.TACKLE ], @@ -3336,13 +3391,15 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 60, Moves.QUASH ], ], [Species.SLOWKING]: [ - [ 1, Moves.TACKLE ], - [ 1, Moves.GROWL ], - [ 1, Moves.WATER_GUN ], - [ 1, Moves.CURSE ], - [ 1, Moves.SWAGGER ], [ 1, Moves.POWER_GEM ], [ 1, Moves.NASTY_PLOT ], + [ 1, Moves.SWAGGER ], + [ 1, Moves.TACKLE ], + [ 1, Moves.CURSE ], + [ 1, Moves.GROWL ], + [ 1, Moves.WATER_GUN ], + [ 1, Moves.FUTURE_SIGHT ], + [ 1, Moves.CHILLY_RECEPTION ], [ 9, Moves.YAWN ], [ 12, Moves.CONFUSION ], [ 15, Moves.DISABLE ], @@ -4559,9 +4616,22 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 64, Moves.HYDRO_PUMP ], ], [Species.LUDICOLO]: [ + [ 1, Moves.FAKE_OUT ], [ 1, Moves.BUBBLE_BEAM ], [ 1, Moves.RAIN_DANCE ], - [ 1, Moves.FAKE_OUT ], + [ 1, Moves.GROWL ], + [ 1, Moves.MIST ], + [ 1, Moves.WATER_GUN ], + [ 1, Moves.HYDRO_PUMP ], + [ 1, Moves.ABSORB ], + [ 1, Moves.MEGA_DRAIN ], + [ 1, Moves.FURY_SWIPES ], + [ 1, Moves.FLAIL ], + [ 1, Moves.KNOCK_OFF ], + [ 1, Moves.TEETER_DANCE ], + [ 1, Moves.ASTONISH ], + [ 1, Moves.ENERGY_BALL ], + [ 1, Moves.ZEN_HEADBUTT ], ], [Species.SEEDOT]: [ [ 1, Moves.TACKLE ], @@ -4601,10 +4671,27 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.SHIFTRY]: [ [ 0, Moves.LEAF_BLADE ], - [ 1, Moves.SUNNY_DAY ], [ 1, Moves.AIR_CUTTER ], - [ 1, Moves.PAYBACK ], [ 1, Moves.HURRICANE ], + [ 1, Moves.PAYBACK ], + [ 1, Moves.SUNNY_DAY ], + [ 1, Moves.WHIRLWIND ], + [ 1, Moves.TACKLE ], + [ 1, Moves.ABSORB ], + [ 1, Moves.MEGA_DRAIN ], + [ 1, Moves.GROWTH ], + [ 1, Moves.RAZOR_LEAF ], + [ 1, Moves.HARDEN ], + [ 1, Moves.EXPLOSION ], + [ 1, Moves.ROLLOUT ], + [ 1, Moves.SWAGGER ], + [ 1, Moves.SYNTHESIS ], + [ 1, Moves.BEAT_UP ], + [ 1, Moves.FAKE_OUT ], + [ 1, Moves.TORMENT ], + [ 1, Moves.ASTONISH ], + [ 1, Moves.EXTRASENSORY ], + [ 1, Moves.SUCKER_PUNCH ], ], [Species.TAILLOW]: [ [ 1, Moves.GROWL ], @@ -9594,21 +9681,21 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 48, Moves.LAST_RESORT ], ], [Species.CINCCINO]: [ + [ 0, Moves.TAIL_SLAP ], + [ 1, Moves.BULLET_SEED ], + [ 1, Moves.SING ], + [ 1, Moves.CHARM ], [ 1, Moves.POUND ], [ 1, Moves.SLAM ], - [ 1, Moves.SING ], [ 1, Moves.SWIFT ], - [ 1, Moves.CHARM ], [ 1, Moves.ENCORE ], [ 1, Moves.HELPING_HAND ], [ 1, Moves.HYPER_VOICE ], [ 1, Moves.TICKLE ], - [ 1, Moves.BULLET_SEED ], [ 1, Moves.ROCK_BLAST ], [ 1, Moves.LAST_RESORT ], [ 1, Moves.AFTER_YOU ], [ 1, Moves.ECHOED_VOICE ], - [ 1, Moves.TAIL_SLAP ], [ 1, Moves.BABY_DOLL_EYES ], ], [Species.GOTHITA]: [ @@ -12401,10 +12488,16 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.VIKAVOLT]: [ [ 0, Moves.THUNDERBOLT ], - [ 1, Moves.STRING_SHOT ], - [ 1, Moves.CRUNCH ], [ 1, Moves.CHARGE ], + [ 1, Moves.CRUNCH ], [ 1, Moves.DISCHARGE ], + [ 1, Moves.STRING_SHOT ], + [ 1, Moves.VISE_GRIP ], + [ 1, Moves.DIG ], + [ 1, Moves.MUD_SLAP ], + [ 1, Moves.IRON_DEFENSE ], + [ 1, Moves.X_SCISSOR ], + [ 1, Moves.BUG_BITE ], [ 15, Moves.BITE ], [ 23, Moves.SPARK ], [ 29, Moves.STICKY_WEB ], @@ -15579,9 +15672,13 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.CERULEDGE]: [ [ 0, Moves.SHADOW_CLAW ], - [ 1, Moves.LEER ], [ 1, Moves.EMBER ], + [ 1, Moves.LEER ], [ 1, Moves.ASTONISH ], + [ 1, Moves.NIGHT_SLASH ], + [ 1, Moves.SHADOW_SNEAK ], + [ 1, Moves.QUICK_GUARD ], + [ 1, Moves.SOLAR_BLADE ], [ 8, Moves.CLEAR_SMOG ], [ 12, Moves.FIRE_SPIN ], [ 16, Moves.WILL_O_WISP ], @@ -16859,6 +16956,7 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.SWEET_SCENT ], [ 1, Moves.RECYCLE ], [ 1, Moves.ASTONISH ], + [ 1, Moves.INFESTATION ], [ 4, Moves.DRAGON_TAIL ], [ 8, Moves.GROWTH ], [ 12, Moves.DRAGON_BREATH ], @@ -16985,6 +17083,9 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 1, Moves.SWEET_SCENT ], [ 1, Moves.RECYCLE ], [ 1, Moves.ASTONISH ], + [ 1, Moves.YAWN ], + [ 1, Moves.DOUBLE_HIT ], + [ 1, Moves.INFESTATION ], [ 4, Moves.DRAGON_TAIL ], [ 8, Moves.GROWTH ], [ 12, Moves.DRAGON_BREATH ], @@ -17178,10 +17279,25 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.ALOLA_SANDSLASH]: [ [ 0, Moves.ICICLE_SPEAR ], - [ 1, Moves.SWORDS_DANCE ], - [ 1, Moves.SLASH ], - [ 1, Moves.METAL_CLAW ], [ 1, Moves.ICICLE_CRASH ], + [ 1, Moves.METAL_CLAW ], + [ 1, Moves.SLASH ], + [ 1, Moves.SWORDS_DANCE ], + [ 1, Moves.SCRATCH ], + [ 1, Moves.MIST ], + [ 1, Moves.BLIZZARD ], + [ 1, Moves.DEFENSE_CURL ], + [ 1, Moves.SWIFT ], + [ 1, Moves.FURY_SWIPES ], + [ 1, Moves.POWDER_SNOW ], + [ 1, Moves.ROLLOUT ], + [ 1, Moves.FURY_CUTTER ], + [ 1, Moves.RAPID_SPIN ], + [ 1, Moves.IRON_DEFENSE ], + [ 1, Moves.GYRO_BALL ], + [ 1, Moves.METAL_BURST ], + [ 1, Moves.IRON_HEAD ], + [ 1, Moves.SNOWSCAPE ], ], [Species.ALOLA_VULPIX]: [ [ 1, Moves.TAIL_WHIP ], @@ -17202,10 +17318,22 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.ALOLA_NINETALES]: [ [ 0, Moves.DAZZLING_GLEAM ], - [ 1, Moves.TAIL_WHIP ], - [ 1, Moves.BLIZZARD ], [ 1, Moves.ICY_WIND ], [ 1, Moves.IMPRISON ], + [ 1, Moves.BLIZZARD ], + [ 1, Moves.TAIL_WHIP ], + [ 1, Moves.DISABLE ], + [ 1, Moves.MIST ], + [ 1, Moves.ICE_BEAM ], + [ 1, Moves.AURORA_BEAM ], + [ 1, Moves.CONFUSE_RAY ], + [ 1, Moves.SPITE ], + [ 1, Moves.POWDER_SNOW ], + [ 1, Moves.EXTRASENSORY ], + [ 1, Moves.NASTY_PLOT ], + [ 1, Moves.ICE_SHARD ], + [ 1, Moves.FREEZE_DRY ], + [ 1, Moves.AURORA_VEIL ], ], [Species.ALOLA_DIGLETT]: [ [ 1, Moves.SAND_ATTACK ], @@ -17365,23 +17493,24 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.ALOLA_EXEGGUTOR]: [ [ 0, Moves.DRAGON_HAMMER ], - [ 1, Moves.ABSORB ], + [ 1, Moves.SEED_BOMB ], + [ 1, Moves.PSYSHOCK ], + [ 1, Moves.WOOD_HAMMER ], + [ 1, Moves.LEAF_STORM ], [ 1, Moves.MEGA_DRAIN ], - [ 1, Moves.LEECH_SEED ], - [ 1, Moves.SOLAR_BEAM ], [ 1, Moves.CONFUSION ], + [ 1, Moves.SYNTHESIS ], + [ 1, Moves.BULLET_SEED ], + [ 1, Moves.GIGA_DRAIN ], + [ 1, Moves.EXTRASENSORY ], + [ 1, Moves.UPROAR ], + [ 1, Moves.WORRY_SEED ], + [ 1, Moves.SOLAR_BEAM ], + [ 1, Moves.ABSORB ], [ 1, Moves.HYPNOSIS ], [ 1, Moves.REFLECT ], - [ 1, Moves.GIGA_DRAIN ], - [ 1, Moves.SYNTHESIS ], - [ 1, Moves.UPROAR ], - [ 1, Moves.EXTRASENSORY ], - [ 1, Moves.BULLET_SEED ], - [ 1, Moves.WORRY_SEED ], - [ 1, Moves.SEED_BOMB ], - [ 1, Moves.LEAF_STORM ], - [ 1, Moves.WOOD_HAMMER ], - [ 1, Moves.PSYSHOCK ], + [ 1, Moves.LEECH_SEED ], + [ 1, Moves.GROWTH ], ], [Species.ALOLA_MAROWAK]: [ [ 0, Moves.SHADOW_BONE ], @@ -17634,13 +17763,16 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { ], [Species.GALAR_SLOWKING]: [ [ 0, Moves.EERIE_SPELL ], - [ 1, Moves.TACKLE ], - [ 1, Moves.GROWL ], - [ 1, Moves.ACID ], - [ 1, Moves.CURSE ], - [ 1, Moves.SWAGGER ], [ 1, Moves.POWER_GEM ], [ 1, Moves.NASTY_PLOT ], + [ 1, Moves.SWAGGER ], + [ 1, Moves.TACKLE ], + [ 1, Moves.CURSE ], + [ 1, Moves.GROWL ], + [ 1, Moves.ACID ], + [ 1, Moves.TOXIC ], + [ 1, Moves.FUTURE_SIGHT ], + [ 1, Moves.CHILLY_RECEPTION ], [ 9, Moves.YAWN ], [ 12, Moves.CONFUSION ], [ 15, Moves.DISABLE ], @@ -18111,10 +18243,11 @@ export const pokemonSpeciesLevelMoves: PokemonSpeciesLevelMoves = { [ 40, Moves.EARTHQUAKE ], ], [Species.BLOODMOON_URSALUNA]: [ + [ 1, Moves.HEADLONG_RUSH ], [ 1, Moves.SCRATCH ], [ 1, Moves.LEER ], [ 1, Moves.LICK ], - [ 1, Moves.HEADLONG_RUSH ], + [ 1, Moves.MOONLIGHT ], [ 8, Moves.FURY_SWIPES ], [ 13, Moves.PAYBACK ], [ 17, Moves.HARDEN ], From d5e462ba7d5045534cd93bb247a544a41d6cae30 Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 24 Apr 2024 14:52:05 -0400 Subject: [PATCH 20/30] Temporarily remove Flamigo from exp sprites --- public/exp-sprites.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/public/exp-sprites.json b/public/exp-sprites.json index 2d71fc831fa..12ada72f917 100644 --- a/public/exp-sprites.json +++ b/public/exp-sprites.json @@ -1069,8 +1069,6 @@ "971", "972", "972", - "973", - "973", "974", "974", "975", @@ -2203,8 +2201,6 @@ "971b", "972b", "972b", - "973b", - "973b", "974b", "974b", "975b", @@ -3335,8 +3331,6 @@ "971sb", "972sb", "972sb", - "973sb", - "973sb", "974sb", "974sb", "975sb", @@ -4474,8 +4468,6 @@ "971s", "972s", "972s", - "973s", - "973s", "974s", "974s", "975s", From ad818aa3148ae16478e232bbf79af52876317f8a Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 24 Apr 2024 19:08:02 -0400 Subject: [PATCH 21/30] Add new API url with fallback --- src/ui/login-form-ui-handler.ts | 6 +--- src/ui/registration-form-ui-handler.ts | 8 ++---- src/utils.ts | 39 ++++++++++++++++++-------- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/ui/login-form-ui-handler.ts b/src/ui/login-form-ui-handler.ts index e5af320aba2..27de954632f 100644 --- a/src/ui/login-form-ui-handler.ts +++ b/src/ui/login-form-ui-handler.ts @@ -59,11 +59,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler { }; if (!this.inputs[0].text) return onFail(i18next.t('menu:emptyUsername')); - const contentType = 'application/x-www-form-urlencoded'; - const headers = { - 'Content-Type': contentType, - }; - fetch(`${Utils.apiUrl}/account/login`, { method: 'POST', headers: headers, body: `username=${encodeURIComponent(this.inputs[0].text)}&password=${encodeURIComponent(this.inputs[1].text)}` }) + Utils.apiPost(`account/login`, `username=${this.inputs[0].text}&password=${this.inputs[1].text}`, 'application/x-www-form-urlencoded') .then(response => { if (!response.ok) return response.text(); diff --git a/src/ui/registration-form-ui-handler.ts b/src/ui/registration-form-ui-handler.ts index 239f8aba1fb..f5ff8c218b4 100644 --- a/src/ui/registration-form-ui-handler.ts +++ b/src/ui/registration-form-ui-handler.ts @@ -74,15 +74,11 @@ export default class RegistrationFormUiHandler extends FormModalUiHandler { return onFail(this.getReadableErrorMessage('invalid password')); if (this.inputs[1].text !== this.inputs[2].text) return onFail(i18next.t('menu:passwordNotMatchingConfirmPassword')); - const contentType = 'application/x-www-form-urlencoded'; - const headers = { - 'Content-Type': contentType, - }; - fetch(`${Utils.apiUrl}/account/register`, { method: 'POST', headers: headers, body: `username=${encodeURIComponent(this.inputs[0].text)}&password=${encodeURIComponent(this.inputs[1].text)}` }) + Utils.apiPost(`account/register`, `username=${encodeURIComponent(this.inputs[0].text)}&password=${encodeURIComponent(this.inputs[1].text)}`, 'application/x-www-form-urlencoded') .then(response => response.text()) .then(response => { if (!response) { - fetch(`${Utils.apiUrl}/account/login`, { method: 'POST', headers: headers, body: `username=${encodeURIComponent(this.inputs[0].text)}&password=${encodeURIComponent(this.inputs[1].text)}` }) + Utils.apiPost(`account/login`, `username=${encodeURIComponent(this.inputs[0].text)}&password=${encodeURIComponent(this.inputs[1].text)}`, 'application/x-www-form-urlencoded') .then(response => { if (!response.ok) return response.text(); diff --git a/src/utils.ts b/src/utils.ts index 3cbbfd84263..c90633ca371 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -212,7 +212,8 @@ export function executeIf(condition: boolean, promiseFunc: () => Promise): export const sessionIdKey = 'pokerogue_sessionId'; export const isLocal = window.location.hostname === 'localhost'; export const serverUrl = isLocal ? 'http://localhost:8001' : ''; -export const apiUrl = isLocal ? serverUrl : 'api'; +export const apiUrl = isLocal ? serverUrl : 'https://api.pokerogue.net'; +export const fallbackApiUrl = isLocal ? serverUrl : 'api'; export function setCookie(cName: string, cValue: string): void { const expiration = new Date(); @@ -233,7 +234,7 @@ export function getCookie(cName: string): string { return ''; } -export function apiFetch(path: string, authed: boolean = false): Promise { +export function apiFetch(path: string, authed: boolean = false, fallback: boolean = false): Promise { return new Promise((resolve, reject) => { const request = {}; if (authed) { @@ -241,24 +242,40 @@ export function apiFetch(path: string, authed: boolean = false): Promise resolve(response)) - .catch(err => reject(err)); + fetch(`${!fallback ? apiUrl : fallbackApiUrl}/${path}`, request) + .then(response => { + if (!response.ok && response.status === 404 && !fallback) + return apiFetch(path, authed, true).then(res => resolve(res)); + resolve(response); + }) + .catch(err => { + if (fallback) + reject(err); + else + apiFetch(path, authed, true).then(res => resolve(res)); + }); }); } -export function apiPost(path: string, data?: any, contentType: string = 'application/json'): Promise { +export function apiPost(path: string, data?: any, contentType: string = 'application/json', authed: boolean = false, fallback: boolean = false): Promise { return new Promise((resolve, reject) => { const headers = { 'Accept': contentType, 'Content-Type': contentType, }; - const sId = getCookie(sessionIdKey); - if (sId) - headers['Authorization'] = sId; - fetch(`${apiUrl}/${path}`, { method: 'POST', headers: headers, body: data }) + if (authed) { + const sId = getCookie(sessionIdKey); + if (sId) + headers['Authorization'] = sId; + } + fetch(`${!fallback ? apiUrl : fallbackApiUrl}/${path}`, { method: 'POST', headers: headers, body: data }) .then(response => resolve(response)) - .catch(err => reject(err)); + .catch(err => { + if (fallback) + reject(err); + else + apiPost(path, data, contentType, authed, true).then(res => resolve(res)); + }); }); } From dc575d44a311ecceb581320468478d7870ea891b Mon Sep 17 00:00:00 2001 From: Edralo Date: Wed, 24 Apr 2024 22:10:03 +0200 Subject: [PATCH 22/30] Implement localisation for pokemon stats & add french locale --- src/data/pokemon-stat.ts | 14 ++++++++------ src/locales/en/pokemon-stat.ts | 16 ++++++++++++++++ src/locales/es/pokemon-stat.ts | 16 ++++++++++++++++ src/locales/fr/pokemon-stat.ts | 16 ++++++++++++++++ src/locales/it/pokemon-stat.ts | 16 ++++++++++++++++ src/plugins/i18n.ts | 10 ++++++++++ 6 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 src/locales/en/pokemon-stat.ts create mode 100644 src/locales/es/pokemon-stat.ts create mode 100644 src/locales/fr/pokemon-stat.ts create mode 100644 src/locales/it/pokemon-stat.ts diff --git a/src/data/pokemon-stat.ts b/src/data/pokemon-stat.ts index 228d25a74ea..b22eaefe876 100644 --- a/src/data/pokemon-stat.ts +++ b/src/data/pokemon-stat.ts @@ -1,3 +1,5 @@ +import i18next from '../plugins/i18n'; + export enum Stat { HP = 0, ATK, @@ -11,22 +13,22 @@ export function getStatName(stat: Stat, shorten: boolean = false) { let ret: string; switch (stat) { case Stat.HP: - ret = !shorten ? 'Max. HP' : 'MaxHP'; + ret = !shorten ? i18next.t('pokemonStat:HP') : i18next.t('pokemonStat:HPshortened'); break; case Stat.ATK: - ret = !shorten ? 'Attack' : 'Atk'; + ret = !shorten ? i18next.t('pokemonStat:ATK') : i18next.t('pokemonStat:ATKshortened'); break; case Stat.DEF: - ret = !shorten ? 'Defense' : 'Def'; + ret = !shorten ? i18next.t('pokemonStat:DEF') : i18next.t('pokemonStat:DEFshortened'); break; case Stat.SPATK: - ret = !shorten ? 'Sp. Atk' : 'SpAtk'; + ret = !shorten ? i18next.t('pokemonStat:SPATK') : i18next.t('pokemonStat:SPATKshortened'); break; case Stat.SPDEF: - ret = !shorten ? 'Sp. Def' : 'SpDef'; + ret = !shorten ? i18next.t('pokemonStat:SPDEF') : i18next.t('pokemonStat:SPDEFshortened'); break; case Stat.SPD: - ret = !shorten ? 'Speed' : 'Spd'; + ret = !shorten ? i18next.t('pokemonStat:SPD') : i18next.t('pokemonStat:SPDshortened'); break; } return ret; diff --git a/src/locales/en/pokemon-stat.ts b/src/locales/en/pokemon-stat.ts new file mode 100644 index 00000000000..7a209461b11 --- /dev/null +++ b/src/locales/en/pokemon-stat.ts @@ -0,0 +1,16 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const pokemonStat: SimpleTranslationEntries = { + "HP": "Max. HP", + "HPshortened": "MaxHP", + "ATK": "Attack", + "ATKshortened": "Atk", + "DEF": "Defense", + "DEFshortened": "Def", + "SPATK": "Sp. Atk", + "SPATKshortened": "SpAtk", + "SPDEF": "Sp. Def", + "SPDEFshortened": "SpDef", + "SPD": "Speed", + "SPDshortened": "Spd" +} as const; \ No newline at end of file diff --git a/src/locales/es/pokemon-stat.ts b/src/locales/es/pokemon-stat.ts new file mode 100644 index 00000000000..7a209461b11 --- /dev/null +++ b/src/locales/es/pokemon-stat.ts @@ -0,0 +1,16 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const pokemonStat: SimpleTranslationEntries = { + "HP": "Max. HP", + "HPshortened": "MaxHP", + "ATK": "Attack", + "ATKshortened": "Atk", + "DEF": "Defense", + "DEFshortened": "Def", + "SPATK": "Sp. Atk", + "SPATKshortened": "SpAtk", + "SPDEF": "Sp. Def", + "SPDEFshortened": "SpDef", + "SPD": "Speed", + "SPDshortened": "Spd" +} as const; \ No newline at end of file diff --git a/src/locales/fr/pokemon-stat.ts b/src/locales/fr/pokemon-stat.ts new file mode 100644 index 00000000000..3ab39f0af23 --- /dev/null +++ b/src/locales/fr/pokemon-stat.ts @@ -0,0 +1,16 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const pokemonStat: SimpleTranslationEntries = { + "HP": "PV", + "HPshortened": "PV", + "ATK": "Attaque", + "ATKshortened": "Atq", + "DEF": "Défense", + "DEFshortened": "Déf", + "SPATK": "Atq. Spé", + "SPATKshortened": "AtqSp", + "SPDEF": "Déf. Spé", + "SPDEFshortened": "DéfSp", + "SPD": "Vitesse", + "SPDshortened": "Vit" +} as const; \ No newline at end of file diff --git a/src/locales/it/pokemon-stat.ts b/src/locales/it/pokemon-stat.ts new file mode 100644 index 00000000000..7a209461b11 --- /dev/null +++ b/src/locales/it/pokemon-stat.ts @@ -0,0 +1,16 @@ +import { SimpleTranslationEntries } from "#app/plugins/i18n"; + +export const pokemonStat: SimpleTranslationEntries = { + "HP": "Max. HP", + "HPshortened": "MaxHP", + "ATK": "Attack", + "ATKshortened": "Atk", + "DEF": "Defense", + "DEFshortened": "Def", + "SPATK": "Sp. Atk", + "SPATKshortened": "SpAtk", + "SPDEF": "Sp. Def", + "SPDEFshortened": "SpDef", + "SPD": "Speed", + "SPDshortened": "Spd" +} as const; \ No newline at end of file diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 23a7a8e1d7d..31ddc2d6c79 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -16,6 +16,11 @@ import { pokemon as enPokemon } from '../locales/en/pokemon'; import { pokemon as esPokemon } from '../locales/es/pokemon'; import { pokemon as frPokemon } from '../locales/fr/pokemon'; +import { pokemonStat as enPokemonStat } from '../locales/en/pokemon-stat'; +import { pokemonStat as esPokemonStat } from '../locales/es/pokemon-stat'; +import { pokemonStat as frPokemonStat } from '../locales/fr/pokemon-stat'; +import { pokemonStat as itPokemonStat } from '../locales/it/pokemon-stat'; + import { commandUiHandler as enCommandUiHandler } from '../locales/en/command-ui-handler'; import { commandUiHandler as esCommandUiHandler } from '../locales/es/command-ui-handler'; import { commandUiHandler as frCommandUiHandler } from '../locales/fr/command-ui-handler'; @@ -71,6 +76,7 @@ export function initI18n(): void { move: enMove, pokeball: enPokeball, pokemon: enPokemon, + pokemonStat: enPokemonStat, commandUiHandler: enCommandUiHandler, }, es: { @@ -78,6 +84,7 @@ export function initI18n(): void { move: esMove, pokeball: esPokeball, pokemon: esPokemon, + pokemonStat: esPokemonStat, commandUiHandler: esCommandUiHandler, }, fr: { @@ -85,10 +92,12 @@ export function initI18n(): void { move: frMove, pokeball: frPokeball, pokemon: frPokemon, + pokemonStat: frPokemonStat, commandUiHandler: frCommandUiHandler, }, it: { menu: itMenu, + pokemonStat: itPokemonStat, }, }, }); @@ -102,6 +111,7 @@ declare module 'i18next' { move: typeof enMove; pokeball: typeof enPokeball; pokemon: typeof enPokemon; + pokemonStat: typeof enPokemonStat; commandUiHandler: typeof enCommandUiHandler; }; } From 97218be59c2d75dd0b24094e1c88cc42307f752a Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 24 Apr 2024 19:26:04 -0400 Subject: [PATCH 23/30] Add back missing authorization headers --- src/system/game-data.ts | 8 ++++---- src/ui/menu-ui-handler.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 575701eb484..5e572f25760 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -272,7 +272,7 @@ export class GameData { const systemData = JSON.stringify(data, (k: any, v: any) => typeof v === 'bigint' ? v <= maxIntAttrValue ? Number(v) : v.toString() : v); if (!bypassLogin) { - Utils.apiPost(`savedata/update?datatype=${GameDataType.SYSTEM}`, systemData) + Utils.apiPost(`savedata/update?datatype=${GameDataType.SYSTEM}`, systemData, undefined, true) .then(response => response.text()) .then(error => { this.scene.ui.savingIcon.hide(); @@ -551,7 +551,7 @@ export class GameData { const sessionData = this.getSessionSaveData(scene); if (!bypassLogin) { - Utils.apiPost(`savedata/update?datatype=${GameDataType.SESSION}&slot=${scene.sessionSlotId}`, JSON.stringify(sessionData)) + Utils.apiPost(`savedata/update?datatype=${GameDataType.SESSION}&slot=${scene.sessionSlotId}`, JSON.stringify(sessionData), undefined, true) .then(response => response.text()) .then(error => { if (error) { @@ -752,7 +752,7 @@ export class GameData { if (success !== null && !success) return resolve([false, false]); const sessionData = this.getSessionSaveData(scene); - Utils.apiPost(`savedata/clear?slot=${slotId}`, JSON.stringify(sessionData)).then(response => { + Utils.apiPost(`savedata/clear?slot=${slotId}`, JSON.stringify(sessionData), undefined, true).then(response => { if (response.ok) loggedInUser.lastSessionSlot = -1; return response.json(); @@ -912,7 +912,7 @@ export class GameData { updateUserInfo().then(success => { if (!success) return displayError(`Could not contact the server. Your ${dataName} data could not be imported.`); - Utils.apiPost(`savedata/update?datatype=${dataType}${dataType === GameDataType.SESSION ? `&slot=${slotId}` : ''}`, dataStr) + Utils.apiPost(`savedata/update?datatype=${dataType}${dataType === GameDataType.SESSION ? `&slot=${slotId}` : ''}`, dataStr, undefined, true) .then(response => response.text()) .then(error => { if (error) { diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index 8b2c5646903..16af6b15d96 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -307,7 +307,7 @@ export default class MenuUiHandler extends MessageUiHandler { case MenuOptions.LOG_OUT: success = true; const doLogout = () => { - Utils.apiPost('account/logout').then(res => { + Utils.apiPost('account/logout', undefined, undefined, true).then(res => { if (!res.ok) console.error(`Log out failed (${res.status}: ${res.statusText})`); Utils.setCookie(Utils.sessionIdKey, ''); From ebad76c335c7c6a2610d21b50ce99fe828a0e650 Mon Sep 17 00:00:00 2001 From: Silvestre Emmanuel Date: Wed, 24 Apr 2024 18:49:39 -0600 Subject: [PATCH 24/30] Added the move category icon to the fight ui --- src/ui/fight-ui-handler.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 8ca6ab6e3d0..1f37c9d01f1 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -6,12 +6,14 @@ import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import * as Utils from "../utils"; import { CommandPhase } from "../phases"; +import { MoveCategory } from "#app/data/move.js"; export default class FightUiHandler extends UiHandler { private movesContainer: Phaser.GameObjects.Container; private typeIcon: Phaser.GameObjects.Sprite; private ppText: Phaser.GameObjects.Text; private cursorObj: Phaser.GameObjects.Image; + private moveCategoryIcon: Phaser.GameObjects.Sprite; protected fieldIndex: integer = 0; protected cursor2: integer = 0; @@ -26,10 +28,15 @@ export default class FightUiHandler extends UiHandler { this.movesContainer = this.scene.add.container(18, -38.7); ui.add(this.movesContainer); - this.typeIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 33, -31, 'types', 'unknown'); + this.typeIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 41, -31, 'types', 'unknown'); this.typeIcon.setVisible(false); ui.add(this.typeIcon); + this.moveCategoryIcon = this.scene.add.sprite((this.scene.game.canvas.width / 6) - 19, -31, 'categories', 'physical'); + this.moveCategoryIcon.setVisible(false); + ui.add(this.moveCategoryIcon); + + this.ppText = addTextObject(this.scene, (this.scene.game.canvas.width / 6) - 18, -15.5, ' / ', TextStyle.WINDOW); this.ppText.setOrigin(1, 0.5); this.ppText.setVisible(false); @@ -120,16 +127,19 @@ export default class FightUiHandler extends UiHandler { if (hasMove) { const pokemonMove = moveset[cursor]; - this.typeIcon.setTexture('types', Type[pokemonMove.getMove().type].toLowerCase()); + this.typeIcon.setTexture('types', Type[pokemonMove.getMove().type].toLowerCase()).setScale(0.65); + this.moveCategoryIcon.setTexture('categories', MoveCategory[pokemonMove.getMove().category].toLowerCase()).setScale(0.8); const maxPP = pokemonMove.getMovePp(); const pp = maxPP - pokemonMove.ppUsed; + this.ppText.setText(`${Utils.padInt(pp, 2, ' ')}/${Utils.padInt(maxPP, 2, ' ')}`); } this.typeIcon.setVisible(hasMove); this.ppText.setVisible(hasMove); + this.moveCategoryIcon.setVisible(hasMove); this.cursorObj.setPosition(13 + (cursor % 2 === 1 ? 100 : 0), -31 + (cursor >= 2 ? 15 : 0)); @@ -151,6 +161,7 @@ export default class FightUiHandler extends UiHandler { this.clearMoves(); this.typeIcon.setVisible(false); this.ppText.setVisible(false); + this.moveCategoryIcon.setVisible(false); this.eraseCursor(); } From 7055ea49c75b046ade0c3a8b1896741a5517f19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Gonz=C3=A1lez?= <71378035+PabloG02@users.noreply.github.com> Date: Thu, 25 Apr 2024 03:10:09 +0200 Subject: [PATCH 25/30] =?UTF-8?q?Support=20localization=20of=20Pok=C3=A9mo?= =?UTF-8?q?n=20abilities=20(#271)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Support localization of Pokemon abilities * Reload ability localization when language is changed * Add Spanish localization for abilities * Add missing French abilities localization * Add missing localize call on abilities --------- Co-authored-by: Flashfyre --- src/battle-scene.ts | 2 + src/data/ability.ts | 838 ++++++++++++++----------- src/locales/en/ability.ts | 1244 +++++++++++++++++++++++++++++++++++++ src/locales/es/ability.ts | 1244 +++++++++++++++++++++++++++++++++++++ src/locales/fr/ability.ts | 1244 +++++++++++++++++++++++++++++++++++++ src/plugins/i18n.ts | 17 + 6 files changed, 4228 insertions(+), 361 deletions(-) create mode 100644 src/locales/en/ability.ts create mode 100644 src/locales/es/ability.ts create mode 100644 src/locales/fr/ability.ts diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 7cb92c451a9..3c869aaba87 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -21,6 +21,7 @@ import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesF import AbilityBar from './ui/ability-bar'; import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from './data/ability'; import { Abilities } from "./data/enums/abilities"; +import { allAbilities } from "./data/ability"; import Battle, { BattleType, FixedBattleConfig, fixedBattles } from './battle'; import { GameMode, GameModes, gameModes } from './game-mode'; import FieldSpritePipeline from './pipelines/field-sprite'; @@ -808,6 +809,7 @@ export default class BattleScene extends SceneBase { const localizable: Localizable[] = [ ...allSpecies, ...allMoves, + ...allAbilities, ...Utils.getEnumValues(ModifierPoolType).map(mpt => getModifierPoolForType(mpt)).map(mp => Object.values(mp).flat().map(mt => mt.modifierType).filter(mt => 'localize' in mt).map(lpb => lpb as unknown as Localizable)).flat() ]; for (let item of localizable) diff --git a/src/data/ability.ts b/src/data/ability.ts index e0bd24b4e62..4b8dee38b62 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -18,8 +18,9 @@ import { Moves } from "./enums/moves"; import { TerrainType } from "./terrain"; import { SpeciesFormChangeManualTrigger } from "./pokemon-forms"; import { Abilities } from "./enums/abilities"; +import i18next, { Localizable } from "#app/plugins/i18n.js"; -export class Ability { +export class Ability implements Localizable { public id: Abilities; public name: string; public description: string; @@ -29,13 +30,20 @@ export class Ability { public attrs: AbAttr[]; public conditions: AbAttrCondition[]; - constructor(id: Abilities, name: string, description: string, generation: integer) { + constructor(id: Abilities, generation: integer) { this.id = id; - this.name = name; - this.description = description; this.generation = generation; this.attrs = []; this.conditions = []; + + this.localize(); + } + + localize(): void { + const i18nKey = Abilities[this.id].split('_').filter(f => f).map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join('') as string; + + this.name = this.id ? i18next.t(`ability:${i18nKey}.name`) as string : ''; + this.description = this.id ? i18next.t(`ability:${i18nKey}.description`) as string : ''; } getAttrs(attrType: { new(...args: any[]): AbAttr }): AbAttr[] { @@ -76,6 +84,16 @@ export class Ability { return this; } + + partial(): this { + this.name += ' (P)'; + return this; + } + + unimplemented(): this { + this.name += ' (N)'; + return this; + } } type AbAttrApplyFunc = (attr: TAttr, passive: boolean) => boolean | Promise; @@ -2409,422 +2427,456 @@ function queueShowAbility(pokemon: Pokemon, passive: boolean): void { pokemon.scene.clearPhaseQueueSplice(); } -export const allAbilities = [ new Ability(Abilities.NONE, "-", "", 3) ]; +export const allAbilities = [ new Ability(Abilities.NONE, 3) ]; export function initAbilities() { allAbilities.push( - new Ability(Abilities.STENCH, "Stench", "By releasing stench when attacking, this Pokémon may cause the target to flinch.", 3) + new Ability(Abilities.STENCH, 3) .attr(PostAttackApplyBattlerTagAbAttr, false, (user, target, move) => !move.getMove().findAttr(attr => attr instanceof FlinchAttr) ? 10 : 0, BattlerTagType.FLINCHED), - new Ability(Abilities.DRIZZLE, "Drizzle", "The Pokémon makes it rain when it enters a battle.", 3) + new Ability(Abilities.DRIZZLE, 3) .attr(PostSummonWeatherChangeAbAttr, WeatherType.RAIN) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.RAIN), - new Ability(Abilities.SPEED_BOOST, "Speed Boost", "Its Speed stat is boosted every turn.", 3) + new Ability(Abilities.SPEED_BOOST, 3) .attr(PostTurnStatChangeAbAttr, BattleStat.SPD, 1), - new Ability(Abilities.BATTLE_ARMOR, "Battle Armor", "Hard armor protects the Pokémon from critical hits.", 3) + new Ability(Abilities.BATTLE_ARMOR, 3) .attr(BlockCritAbAttr) .ignorable(), - new Ability(Abilities.STURDY, "Sturdy", "It cannot be knocked out with one hit. One-hit KO moves cannot knock it out, either.", 3) + new Ability(Abilities.STURDY, 3) .attr(PreDefendFullHpEndureAbAttr) .attr(BlockOneHitKOAbAttr) .ignorable(), - new Ability(Abilities.DAMP, "Damp (N)", "Prevents the use of explosive moves, such as Self-Destruct, by dampening its surroundings.", 3) - .ignorable(), - new Ability(Abilities.LIMBER, "Limber", "Its limber body protects the Pokémon from paralysis.", 3) + new Ability(Abilities.DAMP, 3) + .ignorable() + .unimplemented(), + new Ability(Abilities.LIMBER, 3) .attr(StatusEffectImmunityAbAttr, StatusEffect.PARALYSIS) .ignorable(), - new Ability(Abilities.SAND_VEIL, "Sand Veil", "Boosts the Pokémon's evasiveness in a sandstorm.", 3) + new Ability(Abilities.SAND_VEIL, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.EVA, 1.2) .attr(BlockWeatherDamageAttr, WeatherType.SANDSTORM) .condition(getWeatherCondition(WeatherType.SANDSTORM)) .ignorable(), - new Ability(Abilities.STATIC, "Static", "The Pokémon is charged with static electricity, so contact with it may cause paralysis.", 3) + new Ability(Abilities.STATIC, 3) .attr(PostDefendContactApplyStatusEffectAbAttr, 30, StatusEffect.PARALYSIS), - new Ability(Abilities.VOLT_ABSORB, "Volt Absorb", "Restores HP if hit by an Electric-type move instead of taking damage.", 3) + new Ability(Abilities.VOLT_ABSORB, 3) .attr(TypeImmunityHealAbAttr, Type.ELECTRIC) .ignorable(), - new Ability(Abilities.WATER_ABSORB, "Water Absorb", "Restores HP if hit by a Water-type move instead of taking damage.", 3) + new Ability(Abilities.WATER_ABSORB, 3) .attr(TypeImmunityHealAbAttr, Type.WATER) .ignorable(), - new Ability(Abilities.OBLIVIOUS, "Oblivious", "The Pokémon is oblivious, and that keeps it from being infatuated or falling for taunts.", 3) + new Ability(Abilities.OBLIVIOUS, 3) .attr(BattlerTagImmunityAbAttr, BattlerTagType.INFATUATED) .ignorable(), - new Ability(Abilities.CLOUD_NINE, "Cloud Nine", "Eliminates the effects of weather.", 3) + new Ability(Abilities.CLOUD_NINE, 3) .attr(SuppressWeatherEffectAbAttr, true), - new Ability(Abilities.COMPOUND_EYES, "Compound Eyes", "The Pokémon's compound eyes boost its accuracy.", 3) + new Ability(Abilities.COMPOUND_EYES, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 1.3), - new Ability(Abilities.INSOMNIA, "Insomnia", "The Pokémon is suffering from insomnia and cannot fall asleep.", 3) + new Ability(Abilities.INSOMNIA, 3) .attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .ignorable(), - new Ability(Abilities.COLOR_CHANGE, "Color Change", "The Pokémon's type becomes the type of the move used on it.", 3) + new Ability(Abilities.COLOR_CHANGE, 3) .attr(PostDefendTypeChangeAbAttr), - new Ability(Abilities.IMMUNITY, "Immunity", "The immune system of the Pokémon prevents it from getting poisoned.", 3) + new Ability(Abilities.IMMUNITY, 3) .attr(StatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) .ignorable(), - new Ability(Abilities.FLASH_FIRE, "Flash Fire", "Powers up the Pokémon's Fire-type moves if it's hit by one.", 3) + new Ability(Abilities.FLASH_FIRE, 3) .attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1, (pokemon: Pokemon) => !pokemon.status || pokemon.status.effect !== StatusEffect.FREEZE) .ignorable(), - new Ability(Abilities.SHIELD_DUST, "Shield Dust (N)", "This Pokémon's dust blocks the additional effects of attacks taken.", 3) - .ignorable(), - new Ability(Abilities.OWN_TEMPO, "Own Tempo", "This Pokémon has its own tempo, and that prevents it from becoming confused.", 3) + new Ability(Abilities.SHIELD_DUST, 3) + .ignorable() + .unimplemented(), + new Ability(Abilities.OWN_TEMPO, 3) .attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED) .ignorable(), - new Ability(Abilities.SUCTION_CUPS, "Suction Cups (N)", "This Pokémon uses suction cups to stay in one spot to negate all moves and items that force switching out.", 3) - .ignorable(), - new Ability(Abilities.INTIMIDATE, "Intimidate", "The Pokémon intimidates opposing Pokémon upon entering battle, lowering their Attack stat.", 3) + new Ability(Abilities.SUCTION_CUPS, 3) + .ignorable() + .unimplemented(), + new Ability(Abilities.INTIMIDATE, 3) .attr(PostSummonStatChangeAbAttr, BattleStat.ATK, -1), - new Ability(Abilities.SHADOW_TAG, "Shadow Tag", "This Pokémon steps on the opposing Pokémon's shadow to prevent it from escaping.", 3) + new Ability(Abilities.SHADOW_TAG, 3) .attr(ArenaTrapAbAttr), - new Ability(Abilities.ROUGH_SKIN, "Rough Skin", "This Pokémon inflicts damage with its rough skin to the attacker on contact.", 3) + new Ability(Abilities.ROUGH_SKIN, 3) .attr(PostDefendContactDamageAbAttr, 8) .bypassFaint(), - new Ability(Abilities.WONDER_GUARD, "Wonder Guard", "Its mysterious power only lets supereffective moves hit the Pokémon.", 3) + new Ability(Abilities.WONDER_GUARD, 3) .attr(NonSuperEffectiveImmunityAbAttr) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .ignorable(), - new Ability(Abilities.LEVITATE, "Levitate", "By floating in the air, the Pokémon receives full immunity to all Ground-type moves.", 3) + new Ability(Abilities.LEVITATE, 3) .attr(TypeImmunityAbAttr, Type.GROUND, (pokemon: Pokemon) => !pokemon.getTag(BattlerTagType.IGNORE_FLYING) && !pokemon.scene.arena.getTag(ArenaTagType.GRAVITY) && !pokemon.getTag(BattlerTagType.GROUNDED)) .ignorable(), - new Ability(Abilities.EFFECT_SPORE, "Effect Spore", "Contact with the Pokémon may inflict poison, sleep, or paralysis on its attacker.", 3) + new Ability(Abilities.EFFECT_SPORE, 3) .attr(PostDefendContactApplyStatusEffectAbAttr, 10, StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP), - new Ability(Abilities.SYNCHRONIZE, "Synchronize (N)", "The attacker will receive the same status condition if it inflicts a burn, poison, or paralysis to the Pokémon.", 3) - .attr(SyncEncounterNatureAbAttr), - new Ability(Abilities.CLEAR_BODY, "Clear Body", "Prevents other Pokémon's moves or Abilities from lowering the Pokémon's stats.", 3) + new Ability(Abilities.SYNCHRONIZE, 3) + .attr(SyncEncounterNatureAbAttr) + .unimplemented(), + new Ability(Abilities.CLEAR_BODY, 3) .attr(ProtectStatAbAttr) .ignorable(), - new Ability(Abilities.NATURAL_CURE, "Natural Cure", "All status conditions heal when the Pokémon switches out.", 3) + new Ability(Abilities.NATURAL_CURE, 3) .attr(PreSwitchOutResetStatusAbAttr), - new Ability(Abilities.LIGHTNING_ROD, "Lightning Rod", "The Pokémon draws in all Electric-type moves. Instead of being hit by Electric-type moves, it boosts its Sp. Atk.", 3) + new Ability(Abilities.LIGHTNING_ROD, 3) .attr(RedirectTypeMoveAbAttr, Type.ELECTRIC) .attr(TypeImmunityStatChangeAbAttr, Type.ELECTRIC, BattleStat.SPATK, 1) .ignorable(), - new Ability(Abilities.SERENE_GRACE, "Serene Grace (N)", "Boosts the likelihood of additional effects occurring when attacking.", 3), - new Ability(Abilities.SWIFT_SWIM, "Swift Swim", "Boosts the Pokémon's Speed stat in rain.", 3) + new Ability(Abilities.SERENE_GRACE, 3) + .unimplemented(), + new Ability(Abilities.SWIFT_SWIM, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2) .condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)), - new Ability(Abilities.CHLOROPHYLL, "Chlorophyll", "Boosts the Pokémon's Speed stat in harsh sunlight.", 3) + new Ability(Abilities.CHLOROPHYLL, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2) .condition(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)), - new Ability(Abilities.ILLUMINATE, "Illuminate", "By illuminating its surroundings, the Pokémon raises the likelihood of meeting wild Pokémon and prevents its accuracy from being lowered.", 3) + new Ability(Abilities.ILLUMINATE, 3) .attr(ProtectStatAbAttr, BattleStat.ACC) .attr(DoubleBattleChanceAbAttr) .ignorable(), - new Ability(Abilities.TRACE, "Trace", "When it enters a battle, the Pokémon copies an opposing Pokémon's Ability.", 3) + new Ability(Abilities.TRACE, 3) .attr(TraceAbAttr) .attr(UncopiableAbilityAbAttr), - new Ability(Abilities.HUGE_POWER, "Huge Power", "Doubles the Pokémon's Attack stat.", 3) + new Ability(Abilities.HUGE_POWER, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.ATK, 2), - new Ability(Abilities.POISON_POINT, "Poison Point", "Contact with the Pokémon may poison the attacker.", 3) + new Ability(Abilities.POISON_POINT, 3) .attr(PostDefendContactApplyStatusEffectAbAttr, 30, StatusEffect.POISON), - new Ability(Abilities.INNER_FOCUS, "Inner Focus", "The Pokémon's intensely focused, and that protects the Pokémon from flinching.", 3) + new Ability(Abilities.INNER_FOCUS, 3) .attr(BattlerTagImmunityAbAttr, BattlerTagType.FLINCHED) .ignorable(), - new Ability(Abilities.MAGMA_ARMOR, "Magma Armor", "The Pokémon is covered with hot magma, which prevents the Pokémon from becoming frozen.", 3) + new Ability(Abilities.MAGMA_ARMOR, 3) .attr(StatusEffectImmunityAbAttr, StatusEffect.FREEZE) .ignorable(), - new Ability(Abilities.WATER_VEIL, "Water Veil", "The Pokémon is covered with a water veil, which prevents the Pokémon from getting a burn.", 3) + new Ability(Abilities.WATER_VEIL, 3) .attr(StatusEffectImmunityAbAttr, StatusEffect.BURN) .ignorable(), - new Ability(Abilities.MAGNET_PULL, "Magnet Pull (N)", "Prevents Steel-type Pokémon from escaping using its magnetic force.", 3) + new Ability(Abilities.MAGNET_PULL, 3) /*.attr(ArenaTrapAbAttr) - .condition((pokemon: Pokemon) => pokemon.getOpponent()?.isOfType(Type.STEEL))*/, - new Ability(Abilities.SOUNDPROOF, "Soundproof", "Soundproofing gives the Pokémon full immunity to all sound-based moves.", 3) + .condition((pokemon: Pokemon) => pokemon.getOpponent()?.isOfType(Type.STEEL))*/ + .unimplemented(), + new Ability(Abilities.SOUNDPROOF, 3) .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.SOUND_BASED)) .ignorable(), - new Ability(Abilities.RAIN_DISH, "Rain Dish", "The Pokémon gradually regains HP in rain.", 3) + new Ability(Abilities.RAIN_DISH, 3) .attr(PostWeatherLapseHealAbAttr, 1, WeatherType.RAIN, WeatherType.HEAVY_RAIN), - new Ability(Abilities.SAND_STREAM, "Sand Stream", "The Pokémon summons a sandstorm when it enters a battle.", 3) + new Ability(Abilities.SAND_STREAM, 3) .attr(PostSummonWeatherChangeAbAttr, WeatherType.SANDSTORM) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.SANDSTORM), - new Ability(Abilities.PRESSURE, "Pressure", "By putting pressure on the opposing Pokémon, it raises their PP usage.", 3) + new Ability(Abilities.PRESSURE, 3) .attr(IncreasePpAbAttr) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' is exerting its Pressure!')), - new Ability(Abilities.THICK_FAT, "Thick Fat", "The Pokémon is protected by a layer of thick fat, which halves the damage taken from Fire- and Ice-type moves.", 3) + new Ability(Abilities.THICK_FAT, 3) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.ICE, 0.5) .ignorable(), - new Ability(Abilities.EARLY_BIRD, "Early Bird", "The Pokémon awakens from sleep twice as fast as other Pokémon.", 3) + new Ability(Abilities.EARLY_BIRD, 3) .attr(ReduceStatusEffectDurationAbAttr, StatusEffect.SLEEP), - new Ability(Abilities.FLAME_BODY, "Flame Body", "Contact with the Pokémon may burn the attacker.", 3) + new Ability(Abilities.FLAME_BODY, 3) .attr(PostDefendContactApplyStatusEffectAbAttr, 30, StatusEffect.BURN), - new Ability(Abilities.RUN_AWAY, "Run Away", "Enables a sure getaway from wild Pokémon.", 3) + new Ability(Abilities.RUN_AWAY, 3) .attr(RunSuccessAbAttr), - new Ability(Abilities.KEEN_EYE, "Keen Eye", "Keen eyes prevent other Pokémon from lowering this Pokémon's accuracy.", 3) + new Ability(Abilities.KEEN_EYE, 3) .attr(ProtectStatAbAttr, BattleStat.ACC) .ignorable(), - new Ability(Abilities.HYPER_CUTTER, "Hyper Cutter", "The Pokémon's proud of its powerful pincers. They prevent other Pokémon from lowering its Attack stat.", 3) + new Ability(Abilities.HYPER_CUTTER, 3) .attr(ProtectStatAbAttr, BattleStat.ATK) .ignorable(), - new Ability(Abilities.PICKUP, "Pickup", "The Pokémon may pick up the item an opposing Pokémon held during a battle.", 3) + new Ability(Abilities.PICKUP, 3) .attr(PostBattleLootAbAttr), - new Ability(Abilities.TRUANT, "Truant", "The Pokémon can't use a move if it had used a move on the previous turn.", 3) + new Ability(Abilities.TRUANT, 3) .attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.TRUANT, 1, false), - new Ability(Abilities.HUSTLE, "Hustle", "Boosts the Attack stat, but lowers accuracy.", 3) + new Ability(Abilities.HUSTLE, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.ATK, 1.5) .attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 0.8), - new Ability(Abilities.CUTE_CHARM, "Cute Charm", "Contact with the Pokémon may cause infatuation.", 3) + new Ability(Abilities.CUTE_CHARM, 3) .attr(PostDefendContactApplyTagChanceAbAttr, 30, BattlerTagType.INFATUATED), - new Ability(Abilities.PLUS, "Plus (N)", "Boosts the Sp. Atk stat of the Pokémon if an ally with the Plus or Minus Ability is also in battle.", 3), - new Ability(Abilities.MINUS, "Minus (N)", "Boosts the Sp. Atk stat of the Pokémon if an ally with the Plus or Minus Ability is also in battle.", 3), - new Ability(Abilities.FORECAST, "Forecast (N)", "The Pokémon transforms with the weather to change its type to Water, Fire, or Ice.", 3) + new Ability(Abilities.PLUS, 3) + .unimplemented(), + new Ability(Abilities.MINUS, 3) + .unimplemented(), + new Ability(Abilities.FORECAST, 3) .attr(UncopiableAbilityAbAttr) - .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.STICKY_HOLD, "Sticky Hold", "Items held by the Pokémon are stuck fast and cannot be removed by other Pokémon.", 3) + .attr(NoFusionAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.STICKY_HOLD, 3) .attr(BlockItemTheftAbAttr) .bypassFaint() .ignorable(), - new Ability(Abilities.SHED_SKIN, "Shed Skin", "The Pokémon may heal its own status conditions by shedding its skin.", 3) + new Ability(Abilities.SHED_SKIN, 3) .conditionalAttr(pokemon => !Utils.randSeedInt(3), PostTurnResetStatusAbAttr), - new Ability(Abilities.GUTS, "Guts", "It's so gutsy that having a status condition boosts the Pokémon's Attack stat.", 3) + new Ability(Abilities.GUTS, 3) .attr(BypassBurnDamageReductionAbAttr) .conditionalAttr(pokemon => !!pokemon.status, BattleStatMultiplierAbAttr, BattleStat.ATK, 1.5), - new Ability(Abilities.MARVEL_SCALE, "Marvel Scale", "The Pokémon's marvelous scales boost the Defense stat if it has a status condition.", 3) + new Ability(Abilities.MARVEL_SCALE, 3) .conditionalAttr(pokemon => !!pokemon.status, BattleStatMultiplierAbAttr, BattleStat.DEF, 1.5) .ignorable(), - new Ability(Abilities.LIQUID_OOZE, "Liquid Ooze", "The oozed liquid has a strong stench, which damages attackers using any draining move.", 3) + new Ability(Abilities.LIQUID_OOZE, 3) .attr(ReverseDrainAbAttr), - new Ability(Abilities.OVERGROW, "Overgrow", "Powers up Grass-type moves when the Pokémon's HP is low.", 3) + new Ability(Abilities.OVERGROW, 3) .attr(LowHpMoveTypePowerBoostAbAttr, Type.GRASS), - new Ability(Abilities.BLAZE, "Blaze", "Powers up Fire-type moves when the Pokémon's HP is low.", 3) + new Ability(Abilities.BLAZE, 3) .attr(LowHpMoveTypePowerBoostAbAttr, Type.FIRE), - new Ability(Abilities.TORRENT, "Torrent", "Powers up Water-type moves when the Pokémon's HP is low.", 3) + new Ability(Abilities.TORRENT, 3) .attr(LowHpMoveTypePowerBoostAbAttr, Type.WATER), - new Ability(Abilities.SWARM, "Swarm", "Powers up Bug-type moves when the Pokémon's HP is low.", 3) + new Ability(Abilities.SWARM, 3) .attr(LowHpMoveTypePowerBoostAbAttr, Type.BUG), - new Ability(Abilities.ROCK_HEAD, "Rock Head", "Protects the Pokémon from recoil damage.", 3) + new Ability(Abilities.ROCK_HEAD, 3) .attr(BlockRecoilDamageAttr), - new Ability(Abilities.DROUGHT, "Drought", "Turns the sunlight harsh when the Pokémon enters a battle.", 3) + new Ability(Abilities.DROUGHT, 3) .attr(PostSummonWeatherChangeAbAttr, WeatherType.SUNNY) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.SUNNY), - new Ability(Abilities.ARENA_TRAP, "Arena Trap", "Prevents opposing Pokémon from fleeing.", 3) + new Ability(Abilities.ARENA_TRAP, 3) .attr(ArenaTrapAbAttr), - new Ability(Abilities.VITAL_SPIRIT, "Vital Spirit", "The Pokémon is full of vitality, and that prevents it from falling asleep.", 3) + new Ability(Abilities.VITAL_SPIRIT, 3) .attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .ignorable(), - new Ability(Abilities.WHITE_SMOKE, "White Smoke", "The Pokémon is protected by its white smoke, which prevents other Pokémon from lowering its stats.", 3) + new Ability(Abilities.WHITE_SMOKE, 3) .attr(ProtectStatAbAttr) .ignorable(), - new Ability(Abilities.PURE_POWER, "Pure Power", "Using its pure power, the Pokémon doubles its Attack stat.", 3) + new Ability(Abilities.PURE_POWER, 3) .attr(BattleStatMultiplierAbAttr, BattleStat.ATK, 2), - new Ability(Abilities.SHELL_ARMOR, "Shell Armor", "A hard shell protects the Pokémon from critical hits.", 3) + new Ability(Abilities.SHELL_ARMOR, 3) .attr(BlockCritAbAttr) .ignorable(), - new Ability(Abilities.AIR_LOCK, "Air Lock", "Eliminates the effects of weather.", 3) + new Ability(Abilities.AIR_LOCK, 3) .attr(SuppressWeatherEffectAbAttr, true), - new Ability(Abilities.TANGLED_FEET, "Tangled Feet", "Raises evasiveness if the Pokémon is confused.", 4) + new Ability(Abilities.TANGLED_FEET, 4) .conditionalAttr(pokemon => !!pokemon.getTag(BattlerTagType.CONFUSED), BattleStatMultiplierAbAttr, BattleStat.EVA, 2) .ignorable(), - new Ability(Abilities.MOTOR_DRIVE, "Motor Drive", "Boosts its Speed stat if hit by an Electric-type move instead of taking damage.", 4) + new Ability(Abilities.MOTOR_DRIVE, 4) .attr(TypeImmunityStatChangeAbAttr, Type.ELECTRIC, BattleStat.SPD, 1) .ignorable(), - new Ability(Abilities.RIVALRY, "Rivalry", "Becomes competitive and deals more damage to Pokémon of the same gender, but deals less to Pokémon of the opposite gender.", 4) + new Ability(Abilities.RIVALRY, 4) .attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender === target.gender, 1.25) .attr(MovePowerBoostAbAttr, (user, target, move) => user.gender !== Gender.GENDERLESS && target.gender !== Gender.GENDERLESS && user.gender !== target.gender, 0.75), - new Ability(Abilities.STEADFAST, "Steadfast", "The Pokémon's determination boosts the Speed stat each time the Pokémon flinches.", 4) + new Ability(Abilities.STEADFAST, 4) .attr(FlinchStatChangeAbAttr, BattleStat.SPD, 1), - new Ability(Abilities.SNOW_CLOAK, "Snow Cloak", "Boosts the Pokémon's evasiveness in snow.", 4) + new Ability(Abilities.SNOW_CLOAK, 4) .attr(BattleStatMultiplierAbAttr, BattleStat.EVA, 1.2) .attr(BlockWeatherDamageAttr, WeatherType.HAIL) .condition(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW)) .ignorable(), - new Ability(Abilities.GLUTTONY, "Gluttony", "Makes the Pokémon eat a held Berry when its HP drops to half or less, which is sooner than usual.", 4) + new Ability(Abilities.GLUTTONY, 4) .attr(ReduceBerryUseThresholdAbAttr), - new Ability(Abilities.ANGER_POINT, "Anger Point", "The Pokémon is angered when it takes a critical hit, and that maxes its Attack stat.", 4) + new Ability(Abilities.ANGER_POINT, 4) .attr(PostDefendCritStatChangeAbAttr, BattleStat.ATK, 6), - new Ability(Abilities.UNBURDEN, "Unburden (N)", "Boosts the Speed stat if the Pokémon's held item is used or lost.", 4), - new Ability(Abilities.HEATPROOF, "Heatproof", "The heatproof body of the Pokémon halves the damage from Fire-type moves that hit it.", 4) + new Ability(Abilities.UNBURDEN, 4) + .unimplemented(), + new Ability(Abilities.HEATPROOF, 4) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5) .ignorable(), - new Ability(Abilities.SIMPLE, "Simple", "The stat changes the Pokémon receives are doubled.", 4) + new Ability(Abilities.SIMPLE, 4) .attr(StatChangeMultiplierAbAttr, 2) .ignorable(), - new Ability(Abilities.DRY_SKIN, "Dry Skin", "Restores HP in rain or when hit by Water-type moves. Reduces HP in harsh sunlight, and increases the damage received from Fire-type moves.", 4) + new Ability(Abilities.DRY_SKIN, 4) .attr(PostWeatherLapseDamageAbAttr, 2, WeatherType.SUNNY, WeatherType.HARSH_SUN) .attr(PostWeatherLapseHealAbAttr, 2, WeatherType.RAIN, WeatherType.HEAVY_RAIN) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 1.25) .attr(TypeImmunityHealAbAttr, Type.WATER) .ignorable(), - new Ability(Abilities.DOWNLOAD, "Download", "Compares an opposing Pokémon's Defense and Sp. Def stats before raising its own Attack or Sp. Atk stat—whichever will be more effective.", 4) + new Ability(Abilities.DOWNLOAD, 4) .attr(DownloadAbAttr), - new Ability(Abilities.IRON_FIST, "Iron Fist", "Powers up punching moves.", 4) + new Ability(Abilities.IRON_FIST, 4) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.PUNCHING_MOVE), 1.2), - new Ability(Abilities.POISON_HEAL, "Poison Heal (N)", "Restores HP if the Pokémon is poisoned instead of losing HP.", 4), - new Ability(Abilities.ADAPTABILITY, "Adaptability", "Powers up moves of the same type as the Pokémon.", 4) + new Ability(Abilities.POISON_HEAL, 4) + .unimplemented(), + new Ability(Abilities.ADAPTABILITY, 4) .attr(StabBoostAbAttr), - new Ability(Abilities.SKILL_LINK, "Skill Link", "Maximizes the number of times multistrike moves hit.", 4) + new Ability(Abilities.SKILL_LINK, 4) .attr(MaxMultiHitAbAttr), - new Ability(Abilities.HYDRATION, "Hydration", "Heals status conditions if it's raining.", 4) + new Ability(Abilities.HYDRATION, 4) .attr(PostTurnResetStatusAbAttr) .condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)), - new Ability(Abilities.SOLAR_POWER, "Solar Power", "Boosts the Sp. Atk stat in harsh sunlight, but HP decreases every turn.", 4) + new Ability(Abilities.SOLAR_POWER, 4) .attr(PostWeatherLapseDamageAbAttr, 2, WeatherType.SUNNY, WeatherType.HARSH_SUN) .attr(BattleStatMultiplierAbAttr, BattleStat.SPATK, 1.5) .condition(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)), - new Ability(Abilities.QUICK_FEET, "Quick Feet", "Boosts the Speed stat if the Pokémon has a status condition.", 4) + new Ability(Abilities.QUICK_FEET, 4) .conditionalAttr(pokemon => pokemon.status ? pokemon.status.effect === StatusEffect.PARALYSIS : false, BattleStatMultiplierAbAttr, BattleStat.SPD, 2) .conditionalAttr(pokemon => !!pokemon.status, BattleStatMultiplierAbAttr, BattleStat.SPD, 1.5), - new Ability(Abilities.NORMALIZE, "Normalize", "All the Pokémon's moves become Normal type. The power of those moves is boosted a little.", 4) + new Ability(Abilities.NORMALIZE, 4) .attr(MoveTypeChangeAttr, Type.NORMAL, 1.2, (user, target, move) => move.id !== Moves.HIDDEN_POWER && move.id !== Moves.WEATHER_BALL && move.id !== Moves.NATURAL_GIFT && move.id !== Moves.JUDGMENT && move.id !== Moves.TECHNO_BLAST), - new Ability(Abilities.SNIPER, "Sniper (N)", "Powers up moves if they become critical hits when attacking.", 4), - new Ability(Abilities.MAGIC_GUARD, "Magic Guard", "The Pokémon only takes damage from attacks.", 4) + new Ability(Abilities.SNIPER, 4) + .unimplemented(), + new Ability(Abilities.MAGIC_GUARD, 4) .attr(BlockNonDirectDamageAbAttr), - new Ability(Abilities.NO_GUARD, "No Guard", "The Pokémon employs no-guard tactics to ensure incoming and outgoing attacks always land.", 4) + new Ability(Abilities.NO_GUARD, 4) .attr(AlwaysHitAbAttr) .attr(DoubleBattleChanceAbAttr), - new Ability(Abilities.STALL, "Stall (N)", "The Pokémon moves after all other Pokémon do.", 4), - new Ability(Abilities.TECHNICIAN, "Technician", "Powers up the Pokémon's weaker moves.", 4) + new Ability(Abilities.STALL, 4) + .unimplemented(), + new Ability(Abilities.TECHNICIAN, 4) .attr(MovePowerBoostAbAttr, (user, target, move) => move.power <= 60, 1.5), - new Ability(Abilities.LEAF_GUARD, "Leaf Guard", "Prevents status conditions in harsh sunlight.", 4) + new Ability(Abilities.LEAF_GUARD, 4) .attr(StatusEffectImmunityAbAttr) .condition(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)) .ignorable(), - new Ability(Abilities.KLUTZ, "Klutz (N)", "The Pokémon can't use any held items.", 4), - new Ability(Abilities.MOLD_BREAKER, "Mold Breaker", "Moves can be used on the target regardless of its Abilities.", 4) + new Ability(Abilities.KLUTZ, 4) + .unimplemented(), + new Ability(Abilities.MOLD_BREAKER, 4) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' breaks the mold!')) .attr(MoveAbilityBypassAbAttr), - new Ability(Abilities.SUPER_LUCK, "Super Luck (P)", "The Pokémon is so lucky that the critical-hit ratios of its moves are boosted.", 4) - .attr(BonusCritAbAttr), - new Ability(Abilities.AFTERMATH, "Aftermath", "Damages the attacker if it contacts the Pokémon with a finishing hit.", 4) + new Ability(Abilities.SUPER_LUCK, 4) + .attr(BonusCritAbAttr) + .partial(), + new Ability(Abilities.AFTERMATH, 4) .attr(PostFaintContactDamageAbAttr,4) .bypassFaint(), - new Ability(Abilities.ANTICIPATION, "Anticipation", "The Pokémon can sense an opposing Pokémon's dangerous moves.", 4) + new Ability(Abilities.ANTICIPATION, 4) .conditionalAttr(getAnticipationCondition(), PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' shuddered!')), - new Ability(Abilities.FOREWARN, "Forewarn (N)", "When it enters a battle, the Pokémon can tell one of the moves an opposing Pokémon has.", 4), - new Ability(Abilities.UNAWARE, "Unaware", "When attacking, the Pokémon ignores the target Pokémon's stat changes.", 4) + new Ability(Abilities.FOREWARN, 4) + .unimplemented(), + new Ability(Abilities.UNAWARE, 4) .attr(IgnoreOpponentStatChangesAbAttr) .ignorable(), - new Ability(Abilities.TINTED_LENS, "Tinted Lens", "The Pokémon can use \"not very effective\" moves to deal regular damage.", 4) + new Ability(Abilities.TINTED_LENS, 4) .attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type) <= 0.5, 2), - new Ability(Abilities.FILTER, "Filter", "Reduces the power of supereffective attacks taken.", 4) + new Ability(Abilities.FILTER, 4) .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75) .ignorable(), - new Ability(Abilities.SLOW_START, "Slow Start", "For five turns, the Pokémon's Attack and Speed stats are halved.", 4) + new Ability(Abilities.SLOW_START, 4) .attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.SLOW_START, 5), - new Ability(Abilities.SCRAPPY, "Scrappy (N)", "The Pokémon can hit Ghost-type Pokémon with Normal- and Fighting-type moves.", 4), - new Ability(Abilities.STORM_DRAIN, "Storm Drain", "Draws in all Water-type moves. Instead of being hit by Water-type moves, it boosts its Sp. Atk.", 4) + new Ability(Abilities.SCRAPPY, 4) + .unimplemented(), + new Ability(Abilities.STORM_DRAIN, 4) .attr(RedirectTypeMoveAbAttr, Type.WATER) .attr(TypeImmunityStatChangeAbAttr, Type.WATER, BattleStat.SPATK, 1) .ignorable(), - new Ability(Abilities.ICE_BODY, "Ice Body", "The Pokémon gradually regains HP in snow.", 4) + new Ability(Abilities.ICE_BODY, 4) .attr(BlockWeatherDamageAttr, WeatherType.HAIL) .attr(PostWeatherLapseHealAbAttr, 1, WeatherType.HAIL, WeatherType.SNOW), - new Ability(Abilities.SOLID_ROCK, "Solid Rock", "Reduces the power of supereffective attacks taken.", 4) + new Ability(Abilities.SOLID_ROCK, 4) .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75) .ignorable(), - new Ability(Abilities.SNOW_WARNING, "Snow Warning", "The Pokémon makes it snow when it enters a battle.", 4) + new Ability(Abilities.SNOW_WARNING, 4) .attr(PostSummonWeatherChangeAbAttr, WeatherType.SNOW) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.SNOW), - new Ability(Abilities.HONEY_GATHER, "Honey Gather (N)", "The Pokémon may gather Honey after a battle.", 4), - new Ability(Abilities.FRISK, "Frisk (N)", "When it enters a battle, the Pokémon can check an opposing Pokémon's held item.", 4), - new Ability(Abilities.RECKLESS, "Reckless", "Powers up moves that have recoil damage.", 4) + new Ability(Abilities.HONEY_GATHER, 4) + .unimplemented(), + new Ability(Abilities.FRISK, 4) + .unimplemented(), + new Ability(Abilities.RECKLESS, 4) .attr(MovePowerBoostAbAttr, (user, target, move) => move.getAttrs(RecoilAttr).length && move.id !== Moves.STRUGGLE, 1.2), - new Ability(Abilities.MULTITYPE, "Multitype (N)", "Changes the Pokémon's type to match the Plate or Z-Crystal it holds.", 4) + new Ability(Abilities.MULTITYPE, 4) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) - .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.FLOWER_GIFT, "Flower Gift (P)", "Boosts the Attack and Sp. Def stats of itself and allies in harsh sunlight.", 4) + .attr(NoFusionAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.FLOWER_GIFT, 4) .conditionalAttr(getWeatherCondition(WeatherType.SUNNY || WeatherType.HARSH_SUN), BattleStatMultiplierAbAttr, BattleStat.ATK, 1.5) .conditionalAttr(getWeatherCondition(WeatherType.SUNNY || WeatherType.HARSH_SUN), BattleStatMultiplierAbAttr, BattleStat.SPDEF, 1.5) .attr(UncopiableAbilityAbAttr) .attr(NoFusionAbilityAbAttr) - .ignorable(), - new Ability(Abilities.BAD_DREAMS, "Bad Dreams (N)", "Reduces the HP of sleeping opposing Pokémon.", 4), - new Ability(Abilities.PICKPOCKET, "Pickpocket", "Steals an item from an attacker that made direct contact.", 5) + .ignorable() + .partial(), + new Ability(Abilities.BAD_DREAMS, 4) + .unimplemented(), + new Ability(Abilities.PICKPOCKET, 5) .attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT)), - new Ability(Abilities.SHEER_FORCE, "Sheer Force (N)", "Removes additional effects to increase the power of moves when attacking.", 5), - new Ability(Abilities.CONTRARY, "Contrary", "Makes stat changes have an opposite effect.", 5) + new Ability(Abilities.SHEER_FORCE, 5) + .unimplemented(), + new Ability(Abilities.CONTRARY, 5) .attr(StatChangeMultiplierAbAttr, -1) .ignorable(), - new Ability(Abilities.UNNERVE, "Unnerve", "Unnerves opposing Pokémon and makes them unable to eat Berries.", 5) + new Ability(Abilities.UNNERVE, 5) .attr(PreventBerryUseAbAttr), - new Ability(Abilities.DEFIANT, "Defiant", "Boosts the Pokémon's Attack stat sharply when its stats are lowered.", 5) + new Ability(Abilities.DEFIANT, 5) .attr(PostStatChangeStatChangeAbAttr, (target, statsChanged, levels) => levels < 0, [BattleStat.ATK], 2), - new Ability(Abilities.DEFEATIST, "Defeatist", "Halves the Pokémon's Attack and Sp. Atk stats when its HP becomes half or less.", 5) + new Ability(Abilities.DEFEATIST, 5) .attr(BattleStatMultiplierAbAttr, BattleStat.ATK, 0.5) .attr(BattleStatMultiplierAbAttr, BattleStat.SPATK, 0.5) .condition((pokemon) => pokemon.getHpRatio() <= 0.5), - new Ability(Abilities.CURSED_BODY, "Cursed Body (N)", "May disable a move used on the Pokémon.", 5), - new Ability(Abilities.HEALER, "Healer (N)", "Sometimes heals an ally's status condition.", 5), - new Ability(Abilities.FRIEND_GUARD, "Friend Guard (N)", "Reduces damage done to allies.", 5) - .ignorable(), - new Ability(Abilities.WEAK_ARMOR, "Weak Armor", "Physical attacks to the Pokémon lower its Defense stat but sharply raise its Speed stat.", 5) + new Ability(Abilities.CURSED_BODY, 5) + .unimplemented(), + new Ability(Abilities.HEALER, 5) + .unimplemented(), + new Ability(Abilities.FRIEND_GUARD, 5) + .ignorable() + .unimplemented(), + new Ability(Abilities.WEAK_ARMOR, 5) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL, BattleStat.DEF, -1) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL, BattleStat.SPD, 2), - new Ability(Abilities.HEAVY_METAL, "Heavy Metal", "Doubles the Pokémon's weight.", 5) + new Ability(Abilities.HEAVY_METAL, 5) .attr(WeightMultiplierAbAttr, 2) .ignorable(), - new Ability(Abilities.LIGHT_METAL, "Light Metal", "Halves the Pokémon's weight.", 5) + new Ability(Abilities.LIGHT_METAL, 5) .attr(WeightMultiplierAbAttr, 0.5) .ignorable(), - new Ability(Abilities.MULTISCALE, "Multiscale", "Reduces the amount of damage the Pokémon takes while its HP is full.", 5) + new Ability(Abilities.MULTISCALE, 5) .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getHpRatio() === 1, 0.5) .ignorable(), - new Ability(Abilities.TOXIC_BOOST, "Toxic Boost", "Powers up physical attacks when the Pokémon is poisoned.", 5) + new Ability(Abilities.TOXIC_BOOST, 5) .attr(MovePowerBoostAbAttr, (user, target, move) => move.category === MoveCategory.PHYSICAL && (user.status?.effect === StatusEffect.POISON || user.status?.effect === StatusEffect.TOXIC), 1.5), - new Ability(Abilities.FLARE_BOOST, "Flare Boost", "Powers up special attacks when the Pokémon is burned.", 5) + new Ability(Abilities.FLARE_BOOST, 5) .attr(MovePowerBoostAbAttr, (user, target, move) => move.category === MoveCategory.SPECIAL && user.status?.effect === StatusEffect.BURN, 1.5), - new Ability(Abilities.HARVEST, "Harvest (N)", "May create another Berry after one is used.", 5), - new Ability(Abilities.TELEPATHY, "Telepathy (N)", "Anticipates an ally's attack and dodges it.", 5) - .ignorable(), - new Ability(Abilities.MOODY, "Moody", "Raises one stat sharply and lowers another every turn.", 5) + new Ability(Abilities.HARVEST, 5) + .unimplemented(), + new Ability(Abilities.TELEPATHY, 5) + .ignorable() + .unimplemented(), + new Ability(Abilities.MOODY, 5) .attr(PostTurnStatChangeAbAttr, BattleStat.RAND, 2) .attr(PostTurnStatChangeAbAttr, BattleStat.RAND, -1), - new Ability(Abilities.OVERCOAT, "Overcoat", "Protects the Pokémon from things like sand, hail, and powder.", 5) + new Ability(Abilities.OVERCOAT, 5) .attr(BlockWeatherDamageAttr) .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.POWDER_MOVE)) .ignorable(), - new Ability(Abilities.POISON_TOUCH, "Poison Touch", "May poison a target when the Pokémon makes contact.", 5) + new Ability(Abilities.POISON_TOUCH, 5) .attr(PostAttackContactApplyStatusEffectAbAttr, 30, StatusEffect.POISON), - new Ability(Abilities.REGENERATOR, "Regenerator", "Restores a little HP when withdrawn from battle.", 5) + new Ability(Abilities.REGENERATOR, 5) .attr(PreSwitchOutHealAbAttr), - new Ability(Abilities.BIG_PECKS, "Big Pecks", "Protects the Pokémon from Defense-lowering effects.", 5) + new Ability(Abilities.BIG_PECKS, 5) .attr(ProtectStatAbAttr, BattleStat.DEF) .ignorable(), - new Ability(Abilities.SAND_RUSH, "Sand Rush", "Boosts the Pokémon's Speed stat in a sandstorm.", 5) + new Ability(Abilities.SAND_RUSH, 5) .attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2) .attr(BlockWeatherDamageAttr, WeatherType.SANDSTORM) .condition(getWeatherCondition(WeatherType.SANDSTORM)), - new Ability(Abilities.WONDER_SKIN, "Wonder Skin (N)", "Makes status moves more likely to miss.", 5) - .ignorable(), - new Ability(Abilities.ANALYTIC, "Analytic (N)", "Boosts move power when the Pokémon moves last.", 5), - new Ability(Abilities.ILLUSION, "Illusion (N)", "Comes out disguised as the Pokémon in the party's last spot.", 5) + new Ability(Abilities.WONDER_SKIN, 5) + .ignorable() + .unimplemented(), + new Ability(Abilities.ANALYTIC, 5) + .unimplemented(), + new Ability(Abilities.ILLUSION, 5) .attr(UncopiableAbilityAbAttr) - .attr(UnswappableAbilityAbAttr), - new Ability(Abilities.IMPOSTER, "Imposter", "The Pokémon transforms itself into the Pokémon it's facing.", 5) + .attr(UnswappableAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.IMPOSTER, 5) .attr(PostSummonTransformAbAttr) .attr(UncopiableAbilityAbAttr), - new Ability(Abilities.INFILTRATOR, "Infiltrator (N)", "Passes through the opposing Pokémon's barrier, substitute, and the like and strikes.", 5), - new Ability(Abilities.MUMMY, "Mummy", "Contact with the Pokémon changes the attacker's Ability to Mummy.", 5) + new Ability(Abilities.INFILTRATOR, 5) + .unimplemented(), + new Ability(Abilities.MUMMY, 5) .attr(PostDefendAbilityGiveAbAttr) .bypassFaint(), - new Ability(Abilities.MOXIE, "Moxie", "The Pokémon shows moxie, and that boosts the Attack stat after knocking out any Pokémon.", 5) + new Ability(Abilities.MOXIE, 5) .attr(PostVictoryStatChangeAbAttr, BattleStat.ATK, 1), - new Ability(Abilities.JUSTIFIED, "Justified", "Being hit by a Dark-type move boosts the Attack stat of the Pokémon, for justice.", 5) + new Ability(Abilities.JUSTIFIED, 5) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.DARK && move.category !== MoveCategory.STATUS, BattleStat.ATK, 1), - new Ability(Abilities.RATTLED, "Rattled (P)", "Intimidate or being hit by a Dark-, Ghost-, or Bug-type move will scare the Pokémon and boost its Speed stat.", 5) + new Ability(Abilities.RATTLED, 5) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS && (move.type === Type.DARK || move.type === Type.BUG || - move.type === Type.GHOST), BattleStat.SPD, 1), - new Ability(Abilities.MAGIC_BOUNCE, "Magic Bounce (N)", "Reflects status moves instead of getting hit by them.", 5) - .ignorable(), - new Ability(Abilities.SAP_SIPPER, "Sap Sipper", "Boosts the Attack stat if hit by a Grass-type move instead of taking damage.", 5) + move.type === Type.GHOST), BattleStat.SPD, 1) + .partial(), + new Ability(Abilities.MAGIC_BOUNCE, 5) + .ignorable() + .unimplemented(), + new Ability(Abilities.SAP_SIPPER, 5) .attr(TypeImmunityStatChangeAbAttr, Type.GRASS, BattleStat.ATK, 1) .ignorable(), - new Ability(Abilities.PRANKSTER, "Prankster", "Gives priority to a status move.", 5) + new Ability(Abilities.PRANKSTER, 5) .attr(IncrementMovePriorityAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS), - new Ability(Abilities.SAND_FORCE, "Sand Force", "Boosts the power of Rock-, Ground-, and Steel-type moves in a sandstorm.", 5) + new Ability(Abilities.SAND_FORCE, 5) .attr(MoveTypePowerBoostAbAttr, Type.ROCK, 1.3) .attr(MoveTypePowerBoostAbAttr, Type.GROUND, 1.3) .attr(MoveTypePowerBoostAbAttr, Type.STEEL, 1.3) .attr(BlockWeatherDamageAttr, WeatherType.SANDSTORM) .condition(getWeatherCondition(WeatherType.SANDSTORM)), - new Ability(Abilities.IRON_BARBS, "Iron Barbs", "Inflicts damage on the attacker upon contact with iron barbs.", 5) + new Ability(Abilities.IRON_BARBS, 5) .attr(PostDefendContactDamageAbAttr, 8) .bypassFaint(), - new Ability(Abilities.ZEN_MODE, "Zen Mode", "Changes the Pokémon's shape when HP is half or less.", 5) + new Ability(Abilities.ZEN_MODE, 5) .attr(PostBattleInitFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0) .attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0) .attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 ? 1 : 0) @@ -2832,115 +2884,130 @@ export function initAbilities() { .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.VICTORY_STAR, "Victory Star (P)", "Boosts the accuracy of its allies and itself.", 5) - .attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 1.1), - new Ability(Abilities.TURBOBLAZE, "Turboblaze", "Moves can be used on the target regardless of its Abilities.", 5) + new Ability(Abilities.VICTORY_STAR, 5) + .attr(BattleStatMultiplierAbAttr, BattleStat.ACC, 1.1) + .partial(), + new Ability(Abilities.TURBOBLAZE, 5) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' is radiating a blazing aura!')) .attr(MoveAbilityBypassAbAttr), - new Ability(Abilities.TERAVOLT, "Teravolt", "Moves can be used on the target regardless of its Abilities.", 5) + new Ability(Abilities.TERAVOLT, 5) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' is radiating a bursting aura!')) .attr(MoveAbilityBypassAbAttr), - new Ability(Abilities.AROMA_VEIL, "Aroma Veil (N)", "Protects itself and its allies from attacks that limit their move choices.", 6) - .ignorable(), - new Ability(Abilities.FLOWER_VEIL, "Flower Veil (N)", "Ally Grass-type Pokémon are protected from status conditions and the lowering of their stats.", 6) - .ignorable(), - new Ability(Abilities.CHEEK_POUCH, "Cheek Pouch (N)", "Restores HP as well when the Pokémon eats a Berry.", 6), - new Ability(Abilities.PROTEAN, "Protean (N)", "Changes the Pokémon's type to the type of the move it's about to use.", 6), - new Ability(Abilities.FUR_COAT, "Fur Coat", "Halves the damage from physical moves.", 6) + new Ability(Abilities.AROMA_VEIL, 6) + .ignorable() + .unimplemented(), + new Ability(Abilities.FLOWER_VEIL, 6) + .ignorable() + .unimplemented(), + new Ability(Abilities.CHEEK_POUCH, 6) + .unimplemented(), + new Ability(Abilities.PROTEAN, 6) + .unimplemented(), + new Ability(Abilities.FUR_COAT, 6) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL, 0.5) .ignorable(), - new Ability(Abilities.MAGICIAN, "Magician", "The Pokémon steals the held item of a Pokémon it hits with a move.", 6) + new Ability(Abilities.MAGICIAN, 6) .attr(PostAttackStealHeldItemAbAttr), - new Ability(Abilities.BULLETPROOF, "Bulletproof", "Protects the Pokémon from some ball and bomb moves.", 6) + new Ability(Abilities.BULLETPROOF, 6) .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.BALLBOMB_MOVE)) .ignorable(), - new Ability(Abilities.COMPETITIVE, "Competitive", "Boosts the Sp. Atk stat sharply when a stat is lowered.", 6) + new Ability(Abilities.COMPETITIVE, 6) .attr(PostStatChangeStatChangeAbAttr, (target, statsChanged, levels) => levels < 0, [BattleStat.SPATK], 2), - new Ability(Abilities.STRONG_JAW, "Strong Jaw", "The Pokémon's strong jaw boosts the power of its biting moves.", 6) + new Ability(Abilities.STRONG_JAW, 6) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.BITING_MOVE), 1.5), - new Ability(Abilities.REFRIGERATE, "Refrigerate", "Normal-type moves become Ice-type moves. The power of those moves is boosted a little.", 6) + new Ability(Abilities.REFRIGERATE, 6) .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.ICE, 1.2), - new Ability(Abilities.SWEET_VEIL, "Sweet Veil (P)", "Prevents itself and ally Pokémon from falling asleep.", 6) + new Ability(Abilities.SWEET_VEIL, 6) .attr(StatusEffectImmunityAbAttr, StatusEffect.SLEEP) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) - .ignorable(), - new Ability(Abilities.STANCE_CHANGE, "Stance Change", "The Pokémon changes its form to Blade Forme when it uses an attack move and changes to Shield Forme when it uses King's Shield.", 6) + .ignorable() + .partial(), + new Ability(Abilities.STANCE_CHANGE, 6) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.GALE_WINGS, "Gale Wings", "Gives priority to Flying-type moves when the Pokémon's HP is full.", 6) + new Ability(Abilities.GALE_WINGS, 6) .attr(IncrementMovePriorityAbAttr, (pokemon, move) => pokemon.getHpRatio() === 1 && move.type === Type.FLYING), - new Ability(Abilities.MEGA_LAUNCHER, "Mega Launcher", "Powers up aura and pulse moves.", 6) + new Ability(Abilities.MEGA_LAUNCHER, 6) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.PULSE_MOVE), 1.5), - new Ability(Abilities.GRASS_PELT, "Grass Pelt", "Boosts the Pokémon's Defense stat on Grassy Terrain.", 6) + new Ability(Abilities.GRASS_PELT, 6) .conditionalAttr(getTerrainCondition(TerrainType.GRASSY), BattleStatMultiplierAbAttr, BattleStat.DEF, 1.5) .ignorable(), - new Ability(Abilities.SYMBIOSIS, "Symbiosis (N)", "The Pokémon passes its item to an ally that has used up an item.", 6), - new Ability(Abilities.TOUGH_CLAWS, "Tough Claws", "Powers up moves that make direct contact.", 6) + new Ability(Abilities.SYMBIOSIS, 6) + .unimplemented(), + new Ability(Abilities.TOUGH_CLAWS, 6) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 1.3), - new Ability(Abilities.PIXILATE, "Pixilate", "Normal-type moves become Fairy-type moves. The power of those moves is boosted a little.", 6) + new Ability(Abilities.PIXILATE, 6) .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.FAIRY, 1.2), - new Ability(Abilities.GOOEY, "Gooey", "Contact with the Pokémon lowers the attacker's Speed stat.", 6) + new Ability(Abilities.GOOEY, 6) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), BattleStat.SPD, -1, false), - new Ability(Abilities.AERILATE, "Aerilate", "Normal-type moves become Flying-type moves. The power of those moves is boosted a little.", 6) + new Ability(Abilities.AERILATE, 6) .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.FLYING, 1.2), - new Ability(Abilities.PARENTAL_BOND, "Parental Bond (N)", "Parent and child each attacks.", 6), - new Ability(Abilities.DARK_AURA, "Dark Aura", "Powers up each Pokémon's Dark-type moves.", 6) + new Ability(Abilities.PARENTAL_BOND, 6) + .unimplemented(), + new Ability(Abilities.DARK_AURA, 6) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' is radiating a Dark Aura!')) .attr(FieldMoveTypePowerBoostAbAttr, Type.DARK, 4 / 3), - new Ability(Abilities.FAIRY_AURA, "Fairy Aura", "Powers up each Pokémon's Fairy-type moves.", 6) + new Ability(Abilities.FAIRY_AURA, 6) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => getPokemonMessage(pokemon, ' is radiating a Fairy Aura!')) .attr(FieldMoveTypePowerBoostAbAttr, Type.FAIRY, 4 / 3), - new Ability(Abilities.AURA_BREAK, "Aura Break (N)", "The effects of \"Aura\" Abilities are reversed to lower the power of affected moves.", 6) - .ignorable(), - new Ability(Abilities.PRIMORDIAL_SEA, "Primordial Sea", "The Pokémon changes the weather to nullify Fire-type attacks.", 6) + new Ability(Abilities.AURA_BREAK, 6) + .ignorable() + .unimplemented(), + new Ability(Abilities.PRIMORDIAL_SEA, 6) .attr(PostSummonWeatherChangeAbAttr, WeatherType.HEAVY_RAIN) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HEAVY_RAIN), - new Ability(Abilities.DESOLATE_LAND, "Desolate Land", "The Pokémon changes the weather to nullify Water-type attacks.", 6) + new Ability(Abilities.DESOLATE_LAND, 6) .attr(PostSummonWeatherChangeAbAttr, WeatherType.HARSH_SUN) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.HARSH_SUN), - new Ability(Abilities.DELTA_STREAM, "Delta Stream", "The Pokémon changes the weather to eliminate all of the Flying type's weaknesses.", 6) + new Ability(Abilities.DELTA_STREAM, 6) .attr(PostSummonWeatherChangeAbAttr, WeatherType.STRONG_WINDS) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.STRONG_WINDS), - new Ability(Abilities.STAMINA, "Stamina", "Boosts the Defense stat when hit by an attack.", 7) + new Ability(Abilities.STAMINA, 7) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattleStat.DEF, 1), - new Ability(Abilities.WIMP_OUT, "Wimp Out (N)", "The Pokémon cowardly switches out when its HP becomes half or less.", 7), - new Ability(Abilities.EMERGENCY_EXIT, "Emergency Exit (N)", "The Pokémon, sensing danger, switches out when its HP becomes half or less.", 7), - new Ability(Abilities.WATER_COMPACTION, "Water Compaction", "Boosts the Pokémon's Defense stat sharply when hit by a Water-type move.", 7) + new Ability(Abilities.WIMP_OUT, 7) + .unimplemented(), + new Ability(Abilities.EMERGENCY_EXIT, 7) + .unimplemented(), + new Ability(Abilities.WATER_COMPACTION, 7) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.WATER, BattleStat.DEF, 2), - new Ability(Abilities.MERCILESS, "Merciless (N)", "The Pokémon's attacks become critical hits if the target is poisoned.", 7), - new Ability(Abilities.SHIELDS_DOWN, "Shields Down (P)", "When its HP becomes half or less, the Pokémon's shell breaks and it becomes aggressive.", 7) + new Ability(Abilities.MERCILESS, 7) + .unimplemented(), + new Ability(Abilities.SHIELDS_DOWN, 7) .attr(PostBattleInitFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .attr(PostSummonFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .attr(PostTurnFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) - .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.STAKEOUT, "Stakeout (N)", "Doubles the damage dealt to the target's replacement if the target switches out.", 7), - new Ability(Abilities.WATER_BUBBLE, "Water Bubble", "Lowers the power of Fire-type moves done to the Pokémon and prevents the Pokémon from getting a burn.", 7) + .attr(NoFusionAbilityAbAttr) + .partial(), + new Ability(Abilities.STAKEOUT, 7) + .unimplemented(), + new Ability(Abilities.WATER_BUBBLE, 7) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.FIRE, 0.5) .attr(MoveTypePowerBoostAbAttr, Type.WATER, 1) .attr(StatusEffectImmunityAbAttr, StatusEffect.BURN) .ignorable(), - new Ability(Abilities.STEELWORKER, "Steelworker", "Powers up Steel-type moves.", 7) + new Ability(Abilities.STEELWORKER, 7) .attr(MoveTypePowerBoostAbAttr, Type.STEEL), - new Ability(Abilities.BERSERK, "Berserk (N)", "Boosts the Pokémon's Sp. Atk stat when it takes a hit that causes its HP to become half or less.", 7), - new Ability(Abilities.SLUSH_RUSH, "Slush Rush", "Boosts the Pokémon's Speed stat in snow.", 7) + new Ability(Abilities.BERSERK, 7) + .unimplemented(), + new Ability(Abilities.SLUSH_RUSH, 7) .attr(BattleStatMultiplierAbAttr, BattleStat.SPD, 2) .condition(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW)), - new Ability(Abilities.LONG_REACH, "Long Reach", "The Pokémon uses its moves without making contact with the target.", 7) + new Ability(Abilities.LONG_REACH, 7) .attr(IgnoreContactAbAttr), - new Ability(Abilities.LIQUID_VOICE, "Liquid Voice", "All sound-based moves become Water-type moves.", 7) + new Ability(Abilities.LIQUID_VOICE, 7) .attr(MoveTypeChangeAttr, Type.WATER, 1, (user, target, move) => move.hasFlag(MoveFlags.SOUND_BASED)), - new Ability(Abilities.TRIAGE, "Triage", "Gives priority to a healing move.", 7) + new Ability(Abilities.TRIAGE, 7) .attr(IncrementMovePriorityAbAttr, (pokemon, move) => move.hasFlag(MoveFlags.TRIAGE_MOVE), 3), - new Ability(Abilities.GALVANIZE, "Galvanize", "Normal-type moves become Electric-type moves. The power of those moves is boosted a little.", 7) + new Ability(Abilities.GALVANIZE, 7) .attr(MoveTypeChangePowerMultiplierAbAttr, Type.NORMAL, Type.ELECTRIC, 1.2), - new Ability(Abilities.SURGE_SURFER, "Surge Surfer", "Doubles the Pokémon's Speed stat on Electric Terrain.", 7) + new Ability(Abilities.SURGE_SURFER, 7) .conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), BattleStatMultiplierAbAttr, BattleStat.SPD, 2), - new Ability(Abilities.SCHOOLING, "Schooling", "When it has a lot of HP, the Pokémon forms a powerful school. It stops schooling when its HP is low.", 7) + new Ability(Abilities.SCHOOLING, 7) .attr(PostBattleInitFormChangeAbAttr, p => p.level < 20 || p.getHpRatio() <= 0.25 ? 0 : 1) .attr(PostSummonFormChangeAbAttr, p => p.level < 20 || p.getHpRatio() <= 0.25 ? 0 : 1) .attr(PostTurnFormChangeAbAttr, p => p.level < 20 || p.getHpRatio() <= 0.25 ? 0 : 1) @@ -2948,7 +3015,7 @@ export function initAbilities() { .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.DISGUISE, "Disguise (P)", "Once per battle, the shroud that covers the Pokémon can protect it from an attack.", 7) + new Ability(Abilities.DISGUISE, 7) .attr(PreDefendMovePowerToOneAbAttr, (target, user, move) => target.formIndex == 0 && target.getAttackTypeEffectiveness(move.type) > 0) .attr(PostSummonFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) .attr(PostBattleInitFormChangeAbAttr, p => p.battleData.hitCount === 0 ? 0 : 1) @@ -2960,46 +3027,54 @@ export function initAbilities() { .attr(UnsuppressableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) .attr(NoFusionAbilityAbAttr) - .ignorable(), - new Ability(Abilities.BATTLE_BOND, "Battle Bond (N)", "Defeating an opposing Pokémon strengthens the Pokémon's bond with its Trainer, and it becomes Ash-Greninja. Water Shuriken gets more powerful.", 7) + .ignorable() + .partial(), + new Ability(Abilities.BATTLE_BOND, 7) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) - .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.POWER_CONSTRUCT, "Power Construct (N)", "Other Cells gather to aid when its HP becomes half or less. Then the Pokémon changes its form to Complete Forme.", 7) + .attr(NoFusionAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.POWER_CONSTRUCT, 7) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) - .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.CORROSION, "Corrosion (N)", "The Pokémon can poison the target even if it's a Steel or Poison type.", 7), - new Ability(Abilities.COMATOSE, "Comatose (N)", "It's always drowsing and will never wake up. It can attack without waking up.", 7) + .attr(NoFusionAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.CORROSION, 7) + .unimplemented(), + new Ability(Abilities.COMATOSE, 7) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) - .attr(UnsuppressableAbilityAbAttr), - new Ability(Abilities.QUEENLY_MAJESTY, "Queenly Majesty", "Its majesty pressures the opposing Pokémon, making it unable to attack using priority moves.", 7) + .attr(UnsuppressableAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.QUEENLY_MAJESTY, 7) .attr(FieldPriorityMoveImmunityAbAttr) .ignorable(), - new Ability(Abilities.INNARDS_OUT, "Innards Out (N)", "Damages the attacker landing the finishing hit by the amount equal to its last HP.", 7), - new Ability(Abilities.DANCER, "Dancer (N)", "When another Pokémon uses a dance move, it can use a dance move following it regardless of its Speed.", 7), - new Ability(Abilities.BATTERY, "Battery (N)", "Powers up ally Pokémon's special moves.", 7), - new Ability(Abilities.FLUFFY, "Fluffy", "Halves the damage taken from moves that make direct contact, but doubles that of Fire-type moves.", 7) + new Ability(Abilities.INNARDS_OUT, 7) + .unimplemented(), + new Ability(Abilities.DANCER, 7) + .unimplemented(), + new Ability(Abilities.BATTERY, 7) + .unimplemented(), + new Ability(Abilities.FLUFFY, 7) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 0.5) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.type === Type.FIRE, 2) .ignorable(), - new Ability(Abilities.DAZZLING, "Dazzling", "Surprises the opposing Pokémon, making it unable to attack using priority moves.", 7) + new Ability(Abilities.DAZZLING, 7) .attr(FieldPriorityMoveImmunityAbAttr) .ignorable(), - new Ability(Abilities.SOUL_HEART, "Soul-Heart", "Boosts its Sp. Atk stat every time a Pokémon faints.", 7) + new Ability(Abilities.SOUL_HEART, 7) .attr(PostKnockOutStatChangeAbAttr, BattleStat.SPATK, 1), - new Ability(Abilities.TANGLING_HAIR, "Tangling Hair", "Contact with the Pokémon lowers the attacker's Speed stat.", 7) + new Ability(Abilities.TANGLING_HAIR, 7) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), BattleStat.SPD, -1, false), - new Ability(Abilities.RECEIVER, "Receiver", "The Pokémon copies the Ability of a defeated ally.", 7) + new Ability(Abilities.RECEIVER, 7) .attr(CopyFaintedAllyAbilityAbAttr) .attr(UncopiableAbilityAbAttr), - new Ability(Abilities.POWER_OF_ALCHEMY, "Power of Alchemy", "The Pokémon copies the Ability of a defeated ally.", 7) + new Ability(Abilities.POWER_OF_ALCHEMY, 7) .attr(CopyFaintedAllyAbilityAbAttr) .attr(UncopiableAbilityAbAttr), - new Ability(Abilities.BEAST_BOOST, "Beast Boost", "The Pokémon boosts its most proficient stat each time it knocks out a Pokémon.", 7) + new Ability(Abilities.BEAST_BOOST, 7) .attr(PostVictoryStatChangeAbAttr, p => { const battleStats = Utils.getEnumValues(BattleStat).slice(0, -3).map(s => s as BattleStat); let highestBattleStat = 0; @@ -3013,241 +3088,282 @@ export function initAbilities() { }); return highestBattleStatIndex; }, 1), - new Ability(Abilities.RKS_SYSTEM, "RKS System (N)", "Changes the Pokémon's type to match the memory disc it holds.", 7) + new Ability(Abilities.RKS_SYSTEM, 7) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) - .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.ELECTRIC_SURGE, "Electric Surge", "Turns the ground into Electric Terrain when the Pokémon enters a battle.", 7) + .attr(NoFusionAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.ELECTRIC_SURGE, 7) .attr(PostSummonTerrainChangeAbAttr, TerrainType.ELECTRIC) .attr(PostBiomeChangeTerrainChangeAbAttr, TerrainType.ELECTRIC), - new Ability(Abilities.PSYCHIC_SURGE, "Psychic Surge", "Turns the ground into Psychic Terrain when the Pokémon enters a battle.", 7) + new Ability(Abilities.PSYCHIC_SURGE, 7) .attr(PostSummonTerrainChangeAbAttr, TerrainType.PSYCHIC) .attr(PostBiomeChangeTerrainChangeAbAttr, TerrainType.PSYCHIC), - new Ability(Abilities.MISTY_SURGE, "Misty Surge", "Turns the ground into Misty Terrain when the Pokémon enters a battle.", 7) + new Ability(Abilities.MISTY_SURGE, 7) .attr(PostSummonTerrainChangeAbAttr, TerrainType.MISTY) .attr(PostBiomeChangeTerrainChangeAbAttr, TerrainType.MISTY), - new Ability(Abilities.GRASSY_SURGE, "Grassy Surge", "Turns the ground into Grassy Terrain when the Pokémon enters a battle.", 7) + new Ability(Abilities.GRASSY_SURGE, 7) .attr(PostSummonTerrainChangeAbAttr, TerrainType.GRASSY) .attr(PostBiomeChangeTerrainChangeAbAttr, TerrainType.GRASSY), - new Ability(Abilities.FULL_METAL_BODY, "Full Metal Body", "Prevents other Pokémon's moves or Abilities from lowering the Pokémon's stats.", 7) + new Ability(Abilities.FULL_METAL_BODY, 7) .attr(ProtectStatAbAttr), - new Ability(Abilities.SHADOW_SHIELD, "Shadow Shield", "Reduces the amount of damage the Pokémon takes while its HP is full.", 7) + new Ability(Abilities.SHADOW_SHIELD, 7) .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getHpRatio() === 1, 0.5), - new Ability(Abilities.PRISM_ARMOR, "Prism Armor", "Reduces the power of supereffective attacks taken.", 7) + new Ability(Abilities.PRISM_ARMOR, 7) .attr(ReceivedMoveDamageMultiplierAbAttr,(target, user, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 0.75), - new Ability(Abilities.NEUROFORCE, "Neuroforce", "Powers up moves that are super effective.", 7) + new Ability(Abilities.NEUROFORCE, 7) .attr(MovePowerBoostAbAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type) >= 2, 1.25), - new Ability(Abilities.INTREPID_SWORD, "Intrepid Sword", "Boosts the Pokémon's Attack stat when the Pokémon enters a battle.", 8) + new Ability(Abilities.INTREPID_SWORD, 8) .attr(PostSummonStatChangeAbAttr, BattleStat.ATK, 1, true), - new Ability(Abilities.DAUNTLESS_SHIELD, "Dauntless Shield", "Boosts the Pokémon's Defense stat when the Pokémon enters a battle.", 8) + new Ability(Abilities.DAUNTLESS_SHIELD, 8) .attr(PostSummonStatChangeAbAttr, BattleStat.DEF, 1, true), - new Ability(Abilities.LIBERO, "Libero (N)", "Changes the Pokémon's type to the type of the move it's about to use.", 8), - new Ability(Abilities.BALL_FETCH, "Ball Fetch (N)", "The Pokémon will fetch the Poké Ball from the first failed throw of the battle.", 8), - new Ability(Abilities.COTTON_DOWN, "Cotton Down (N)", "When the Pokémon is hit by an attack, it scatters cotton fluff around and lowers the Speed stat of all Pokémon except itself.", 8), - new Ability(Abilities.PROPELLER_TAIL, "Propeller Tail (N)", "Ignores the effects of opposing Pokémon's Abilities and moves that draw in moves.", 8), - new Ability(Abilities.MIRROR_ARMOR, "Mirror Armor (N)", "Bounces back only the stat-lowering effects that the Pokémon receives.", 8) - .ignorable(), - new Ability(Abilities.GULP_MISSILE, "Gulp Missile (N)", "When the Pokémon uses Surf or Dive, it will come back with prey. When it takes damage, it will spit out the prey to attack.", 8) + new Ability(Abilities.LIBERO, 8) + .unimplemented(), + new Ability(Abilities.BALL_FETCH, 8) + .unimplemented(), + new Ability(Abilities.COTTON_DOWN, 8) + .unimplemented(), + new Ability(Abilities.PROPELLER_TAIL, 8) + .unimplemented(), + new Ability(Abilities.MIRROR_ARMOR, 8) + .ignorable() + .unimplemented(), + new Ability(Abilities.GULP_MISSILE, 8) .attr(UnsuppressableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) - .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.STALWART, "Stalwart (N)", "Ignores the effects of opposing Pokémon's Abilities and moves that draw in moves.", 8), - new Ability(Abilities.STEAM_ENGINE, "Steam Engine", "Boosts the Pokémon's Speed stat drastically if hit by a Fire- or Water-type move.", 8) + .attr(NoFusionAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.STALWART, 8) + .unimplemented(), + new Ability(Abilities.STEAM_ENGINE, 8) .attr(PostDefendStatChangeAbAttr, (target, user, move) => (move.type === Type.FIRE || move.type === Type.WATER) && move.category !== MoveCategory.STATUS, BattleStat.SPD, 6), - new Ability(Abilities.PUNK_ROCK, "Punk Rock", "Boosts the power of sound-based moves. The Pokémon also takes half the damage from these kinds of moves.", 8) + new Ability(Abilities.PUNK_ROCK, 8) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.SOUND_BASED), 1.3) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.hasFlag(MoveFlags.SOUND_BASED), 0.5) .ignorable(), - new Ability(Abilities.SAND_SPIT, "Sand Spit", "The Pokémon creates a sandstorm when it's hit by an attack.", 8) + new Ability(Abilities.SAND_SPIT, 8) .attr(PostDefendWeatherChangeAbAttr, WeatherType.SANDSTORM), - new Ability(Abilities.ICE_SCALES, "Ice Scales", "The Pokémon is protected by ice scales, which halve the damage taken from special moves.", 8) + new Ability(Abilities.ICE_SCALES, 8) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.category === MoveCategory.SPECIAL, 0.5) .ignorable(), - new Ability(Abilities.RIPEN, "Ripen", "Ripens Berries and doubles their effect.", 8) + new Ability(Abilities.RIPEN, 8) .attr(DoubleBerryEffectAbAttr), - new Ability(Abilities.ICE_FACE, "Ice Face (N)", "The Pokémon's ice head can take a physical attack as a substitute, but the attack also changes the Pokémon's appearance. The ice will be restored when it hails.", 8) + new Ability(Abilities.ICE_FACE, 8) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) .attr(NoFusionAbilityAbAttr) - .ignorable(), - new Ability(Abilities.POWER_SPOT, "Power Spot (N)", "Just being next to the Pokémon powers up moves.", 8), - new Ability(Abilities.MIMICRY, "Mimicry (N)", "Changes the Pokémon's type depending on the terrain.", 8), - new Ability(Abilities.SCREEN_CLEANER, "Screen Cleaner (N)", "When the Pokémon enters a battle, the effects of Light Screen, Reflect, and Aurora Veil are nullified for both opposing and ally Pokémon.", 8), - new Ability(Abilities.STEELY_SPIRIT, "Steely Spirit (N)", "Powers up ally Pokémon's Steel-type moves.", 8), - new Ability(Abilities.PERISH_BODY, "Perish Body (N)", "When hit by a move that makes direct contact, the Pokémon and the attacker will faint after three turns unless they switch out of battle.", 8), - new Ability(Abilities.WANDERING_SPIRIT, "Wandering Spirit (P)", "The Pokémon exchanges Abilities with a Pokémon that hits it with a move that makes direct contact.", 8) + .ignorable() + .unimplemented(), + new Ability(Abilities.POWER_SPOT, 8) + .unimplemented(), + new Ability(Abilities.MIMICRY, 8) + .unimplemented(), + new Ability(Abilities.SCREEN_CLEANER, 8) + .unimplemented(), + new Ability(Abilities.STEELY_SPIRIT, 8) + .unimplemented(), + new Ability(Abilities.PERISH_BODY, 8) + .unimplemented(), + new Ability(Abilities.WANDERING_SPIRIT, 8) .attr(PostDefendAbilitySwapAbAttr) - .bypassFaint(), - new Ability(Abilities.GORILLA_TACTICS, "Gorilla Tactics (N)", "Boosts the Pokémon's Attack stat but only allows the use of the first selected move.", 8), - new Ability(Abilities.NEUTRALIZING_GAS, "Neutralizing Gas (P)", "If the Pokémon with Neutralizing Gas is in the battle, the effects of all Pokémon's Abilities will be nullified or will not be triggered.", 8) + .bypassFaint() + .partial(), + new Ability(Abilities.GORILLA_TACTICS, 8) + .unimplemented(), + new Ability(Abilities.NEUTRALIZING_GAS, 8) .attr(SuppressFieldAbilitiesAbAttr) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) - .attr(NoTransformAbilityAbAttr), - new Ability(Abilities.PASTEL_VEIL, "Pastel Veil", "Protects the Pokémon and its ally Pokémon from being poisoned.", 8) + .attr(NoTransformAbilityAbAttr) + .partial(), + new Ability(Abilities.PASTEL_VEIL, 8) .attr(StatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) .ignorable(), - new Ability(Abilities.HUNGER_SWITCH, "Hunger Switch", "The Pokémon changes its form, alternating between its Full Belly Mode and Hangry Mode after the end of each turn.", 8) + new Ability(Abilities.HUNGER_SWITCH, 8) .attr(PostTurnFormChangeAbAttr, p => p.getFormKey ? 0 : 1) .attr(PostTurnFormChangeAbAttr, p => p.getFormKey ? 1 : 0) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.QUICK_DRAW, "Quick Draw (N)", "Enables the Pokémon to move first occasionally.", 8), - new Ability(Abilities.UNSEEN_FIST, "Unseen Fist (N)", "If the Pokémon uses moves that make direct contact, it can attack the target even if the target protects itself.", 8), - new Ability(Abilities.CURIOUS_MEDICINE, "Curious Medicine (N)", "When the Pokémon enters a battle, it scatters medicine from its shell, which removes all stat changes from allies.", 8), - new Ability(Abilities.TRANSISTOR, "Transistor", "Powers up Electric-type moves.", 8) + new Ability(Abilities.QUICK_DRAW, 8) + .unimplemented(), + new Ability(Abilities.UNSEEN_FIST, 8) + .unimplemented(), + new Ability(Abilities.CURIOUS_MEDICINE, 8) + .unimplemented(), + new Ability(Abilities.TRANSISTOR, 8) .attr(MoveTypePowerBoostAbAttr, Type.ELECTRIC), - new Ability(Abilities.DRAGONS_MAW, "Dragon's Maw", "Powers up Dragon-type moves.", 8) + new Ability(Abilities.DRAGONS_MAW, 8) .attr(MoveTypePowerBoostAbAttr, Type.DRAGON), - new Ability(Abilities.CHILLING_NEIGH, "Chilling Neigh", "When the Pokémon knocks out a target, it utters a chilling neigh, which boosts its Attack stat.", 8) + new Ability(Abilities.CHILLING_NEIGH, 8) .attr(PostVictoryStatChangeAbAttr, BattleStat.ATK, 1), - new Ability(Abilities.GRIM_NEIGH, "Grim Neigh", "When the Pokémon knocks out a target, it utters a terrifying neigh, which boosts its Sp. Atk stat.", 8) + new Ability(Abilities.GRIM_NEIGH, 8) .attr(PostVictoryStatChangeAbAttr, BattleStat.SPATK, 1), - new Ability(Abilities.AS_ONE_GLASTRIER, "As One", "This Ability combines the effects of both Calyrex's Unnerve Ability and Glastrier's Chilling Neigh Ability.", 8) + new Ability(Abilities.AS_ONE_GLASTRIER, 8) .attr(PreventBerryUseAbAttr) .attr(PostVictoryStatChangeAbAttr, BattleStat.ATK, 1) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr), - new Ability(Abilities.AS_ONE_SPECTRIER, "As One", "This Ability combines the effects of both Calyrex's Unnerve Ability and Spectrier's Grim Neigh Ability.", 8) + new Ability(Abilities.AS_ONE_SPECTRIER, 8) .attr(PreventBerryUseAbAttr) .attr(PostVictoryStatChangeAbAttr, BattleStat.SPATK, 1) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr), - new Ability(Abilities.LINGERING_AROMA, "Lingering Aroma", "Contact with the Pokémon changes the attacker's Ability to Lingering Aroma.", 9) + new Ability(Abilities.LINGERING_AROMA, 9) .attr(PostDefendAbilityGiveAbAttr) .bypassFaint(), - new Ability(Abilities.SEED_SOWER, "Seed Sower", "Turns the ground into Grassy Terrain when the Pokémon is hit by an attack.", 9) + new Ability(Abilities.SEED_SOWER, 9) .attr(PostDefendTerrainChangeAbAttr, TerrainType.GRASSY), - new Ability(Abilities.THERMAL_EXCHANGE, "Thermal Exchange", "Boosts the Attack stat when the Pokémon is hit by a Fire-type move. The Pokémon also cannot be burned.", 9) + new Ability(Abilities.THERMAL_EXCHANGE, 9) .attr(PostDefendStatChangeAbAttr, (target, user, move) => move.type === Type.FIRE && move.category !== MoveCategory.STATUS, BattleStat.ATK, 1) .attr(StatusEffectImmunityAbAttr, StatusEffect.BURN) .ignorable(), - new Ability(Abilities.ANGER_SHELL, "Anger Shell (N)", "When an attack causes its HP to drop to half or less, the Pokémon gets angry. This lowers its Defense and Sp. Def stats but boosts its Attack, Sp. Atk, and Speed stats.", 9), - new Ability(Abilities.PURIFYING_SALT, "Purifying Salt", "The Pokémon's pure salt protects it from status conditions and halves the damage taken from Ghost-type moves.", 9) + new Ability(Abilities.ANGER_SHELL, 9) + .unimplemented(), + new Ability(Abilities.PURIFYING_SALT, 9) .attr(StatusEffectImmunityAbAttr) .attr(ReceivedTypeDamageMultiplierAbAttr, Type.GHOST, 0.5) .ignorable(), - new Ability(Abilities.WELL_BAKED_BODY, "Well-Baked Body", "The Pokémon takes no damage when hit by Fire-type moves. Instead, its Defense stat is sharply boosted.", 9) + new Ability(Abilities.WELL_BAKED_BODY, 9) .attr(TypeImmunityStatChangeAbAttr, Type.FIRE, BattleStat.DEF, 2) .ignorable(), - new Ability(Abilities.WIND_RIDER, "Wind Rider (P)", "Boosts the Pokémon's Attack stat if Tailwind takes effect or if the Pokémon is hit by a wind move. The Pokémon also takes no damage from wind moves.", 9) + new Ability(Abilities.WIND_RIDER, 9) .attr(MoveImmunityStatChangeAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().hasFlag(MoveFlags.WIND_MOVE), BattleStat.ATK, 1) - .ignorable(), - new Ability(Abilities.GUARD_DOG, "Guard Dog (N)", "Boosts the Pokémon's Attack stat if intimidated. Moves and items that would force the Pokémon to switch out also fail to work.", 9) - .ignorable(), - new Ability(Abilities.ROCKY_PAYLOAD, "Rocky Payload", "Powers up Rock-type moves.", 9) + .ignorable() + .partial(), + new Ability(Abilities.GUARD_DOG, 9) + .ignorable() + .unimplemented(), + new Ability(Abilities.ROCKY_PAYLOAD, 9) .attr(MoveTypePowerBoostAbAttr, Type.ROCK), - new Ability(Abilities.WIND_POWER, "Wind Power (P)", "The Pokémon becomes charged when it is hit by a wind move, boosting the power of the next Electric-type move the Pokémon uses.", 9) - .attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.hasFlag(MoveFlags.WIND_MOVE), BattlerTagType.CHARGED), - new Ability(Abilities.ZERO_TO_HERO, "Zero to Hero (N)", "The Pokémon transforms into its Hero Form when it switches out.", 9) + new Ability(Abilities.WIND_POWER, 9) + .attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.hasFlag(MoveFlags.WIND_MOVE), BattlerTagType.CHARGED) + .partial(), + new Ability(Abilities.ZERO_TO_HERO, 9) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) - .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.COMMANDER, "Commander (N)", "When the Pokémon enters a battle, it goes inside the mouth of an ally Dondozo if one is on the field. The Pokémon then issues commands from there.", 9) + .attr(NoFusionAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.COMMANDER, 9) .attr(UncopiableAbilityAbAttr) - .attr(UnswappableAbilityAbAttr), - new Ability(Abilities.ELECTROMORPHOSIS, "Electromorphosis", "The Pokémon becomes charged when it takes damage, boosting the power of the next Electric-type move the Pokémon uses.", 9) + .attr(UnswappableAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.ELECTROMORPHOSIS, 9) .attr(PostDefendApplyBattlerTagAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, BattlerTagType.CHARGED), - new Ability(Abilities.PROTOSYNTHESIS, "Protosynthesis", "Boosts the Pokémon's most proficient stat in harsh sunlight or if the Pokémon is holding Booster Energy.", 9) + new Ability(Abilities.PROTOSYNTHESIS, 9) .conditionalAttr(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN), PostSummonAddBattlerTagAbAttr, BattlerTagType.PROTOSYNTHESIS, 0, true) .attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.PROTOSYNTHESIS, 0, WeatherType.SUNNY, WeatherType.HARSH_SUN) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr), - new Ability(Abilities.QUARK_DRIVE, "Quark Drive", "Boosts the Pokémon's most proficient stat on Electric Terrain or if the Pokémon is holding Booster Energy.", 9) + new Ability(Abilities.QUARK_DRIVE, 9) .conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), PostSummonAddBattlerTagAbAttr, BattlerTagType.QUARK_DRIVE, 0, true) .attr(PostTerrainChangeAddBattlerTagAttr, BattlerTagType.QUARK_DRIVE, 0, TerrainType.ELECTRIC) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr), - new Ability(Abilities.GOOD_AS_GOLD, "Good as Gold (P)", "A body of pure, solid gold gives the Pokémon full immunity to other Pokémon's status moves.", 9) + new Ability(Abilities.GOOD_AS_GOLD, 9) .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.getMove().category === MoveCategory.STATUS) - .ignorable(), - new Ability(Abilities.VESSEL_OF_RUIN, "Vessel of Ruin (N)", "The power of the Pokémon's ruinous vessel lowers the Sp. Atk stats of all Pokémon except itself.", 9) - .ignorable(), - new Ability(Abilities.SWORD_OF_RUIN, "Sword of Ruin (N)", "The power of the Pokémon's ruinous sword lowers the Defense stats of all Pokémon except itself.", 9) - .ignorable(), - new Ability(Abilities.TABLETS_OF_RUIN, "Tablets of Ruin (N)", "The power of the Pokémon's ruinous wooden tablets lowers the Attack stats of all Pokémon except itself.", 9) - .ignorable(), - new Ability(Abilities.BEADS_OF_RUIN, "Beads of Ruin (N)", "The power of the Pokémon's ruinous beads lowers the Sp. Def stats of all Pokémon except itself.", 9) - .ignorable(), - new Ability(Abilities.ORICHALCUM_PULSE, "Orichalcum Pulse", "Turns the sunlight harsh when the Pokémon enters a battle. The ancient pulse thrumming through the Pokémon also boosts its Attack stat in harsh sunlight.", 9) + .ignorable() + .partial(), + new Ability(Abilities.VESSEL_OF_RUIN, 9) + .ignorable() + .unimplemented(), + new Ability(Abilities.SWORD_OF_RUIN, 9) + .ignorable() + .unimplemented(), + new Ability(Abilities.TABLETS_OF_RUIN, 9) + .ignorable() + .unimplemented(), + new Ability(Abilities.BEADS_OF_RUIN, 9) + .ignorable() + .unimplemented(), + new Ability(Abilities.ORICHALCUM_PULSE, 9) .attr(PostSummonWeatherChangeAbAttr, WeatherType.SUNNY) .attr(PostBiomeChangeWeatherChangeAbAttr, WeatherType.SUNNY) .conditionalAttr(getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN), BattleStatMultiplierAbAttr, BattleStat.ATK, 4 / 3), - new Ability(Abilities.HADRON_ENGINE, "Hadron Engine", "Turns the ground into Electric Terrain when the Pokémon enters a battle. The futuristic engine within the Pokémon also boosts its Sp. Atk stat on Electric Terrain.", 9) + new Ability(Abilities.HADRON_ENGINE, 9) .attr(PostSummonTerrainChangeAbAttr, TerrainType.ELECTRIC) .attr(PostBiomeChangeTerrainChangeAbAttr, TerrainType.ELECTRIC) .conditionalAttr(getTerrainCondition(TerrainType.ELECTRIC), BattleStatMultiplierAbAttr, BattleStat.SPATK, 4 / 3), - new Ability(Abilities.OPPORTUNIST, "Opportunist (N)", "If an opponent's stat is boosted, the Pokémon seizes the opportunity to boost the same stat for itself.", 9), - new Ability(Abilities.CUD_CHEW, "Cud Chew (N)", "When the Pokémon eats a Berry, it will regurgitate that Berry at the end of the next turn and eat it one more time.", 9), - new Ability(Abilities.SHARPNESS, "Sharpness", "Powers up slicing moves.", 9) + new Ability(Abilities.OPPORTUNIST, 9) + .unimplemented(), + new Ability(Abilities.CUD_CHEW, 9) + .unimplemented(), + new Ability(Abilities.SHARPNESS, 9) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.SLICING_MOVE), 1.5), - new Ability(Abilities.SUPREME_OVERLORD, "Supreme Overlord (N)", "When the Pokémon enters a battle, its Attack and Sp. Atk stats are slightly boosted for each of the allies in its party that have already been defeated.", 9), - new Ability(Abilities.COSTAR, "Costar (N)", "When the Pokémon enters a battle, it copies an ally's stat changes.", 9), - new Ability(Abilities.TOXIC_DEBRIS, "Toxic Debris", "Scatters poison spikes at the feet of the opposing team when the Pokémon takes damage from physical moves.", 9) + new Ability(Abilities.SUPREME_OVERLORD, 9) + .unimplemented(), + new Ability(Abilities.COSTAR, 9) + .unimplemented(), + new Ability(Abilities.TOXIC_DEBRIS, 9) .attr(PostDefendApplyArenaTrapTagAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL, ArenaTagType.TOXIC_SPIKES) .bypassFaint(), - new Ability(Abilities.ARMOR_TAIL, "Armor Tail", "The mysterious tail covering the Pokémon's head makes opponents unable to use priority moves against the Pokémon or its allies.", 9) + new Ability(Abilities.ARMOR_TAIL, 9) .attr(FieldPriorityMoveImmunityAbAttr) .ignorable(), - new Ability(Abilities.EARTH_EATER, "Earth Eater", "If hit by a Ground-type move, the Pokémon has its HP restored instead of taking damage.", 9) + new Ability(Abilities.EARTH_EATER, 9) .attr(TypeImmunityHealAbAttr, Type.GROUND) .ignorable(), - new Ability(Abilities.MYCELIUM_MIGHT, "Mycelium Might (P)", "The Pokémon will always act more slowly when using status moves, but these moves will be unimpeded by the Ability of the target.", 9) - .attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS), - new Ability(Abilities.MINDS_EYE, "Mind's Eye (N)", "The Pokémon ignores changes to opponents' evasiveness, its accuracy can't be lowered, and it can hit Ghost types with Normal- and Fighting-type moves.", 9) - .ignorable(), - new Ability(Abilities.SUPERSWEET_SYRUP, "Supersweet Syrup (N)", "A sickly sweet scent spreads across the field the first time the Pokémon enters a battle, lowering the evasiveness of opposing Pokémon.", 9), - new Ability(Abilities.HOSPITALITY, "Hospitality", "When the Pokémon enters a battle, it showers its ally with hospitality, restoring a small amount of the ally's HP.", 9) + new Ability(Abilities.MYCELIUM_MIGHT, 9) + .attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS) + .partial(), + new Ability(Abilities.MINDS_EYE, 9) + .ignorable() + .unimplemented(), + new Ability(Abilities.SUPERSWEET_SYRUP, 9) + .unimplemented(), + new Ability(Abilities.HOSPITALITY, 9) .attr(PostSummonAllyHealAbAttr, 4, true), - new Ability(Abilities.TOXIC_CHAIN, "Toxic Chain", "The power of the Pokémon's toxic chain may badly poison any target the Pokémon hits with a move.", 9) + new Ability(Abilities.TOXIC_CHAIN, 9) .attr(PostAttackApplyStatusEffectAbAttr, false, 30, StatusEffect.TOXIC), - new Ability(Abilities.EMBODY_ASPECT_TEAL, "Embody Aspect", "The Pokémon's heart fills with memories, causing the Teal Mask to shine and the Pokémon's Speed stat to be boosted.", 9) + new Ability(Abilities.EMBODY_ASPECT_TEAL, 9) .attr(PostBattleInitStatChangeAbAttr, BattleStat.SPD, 1, true) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr), - new Ability(Abilities.EMBODY_ASPECT_WELLSPRING, "Embody Aspect", "The Pokémon's heart fills with memories, causing the Wellspring Mask to shine and the Pokémon's Sp. Def stat to be boosted.", 9) + new Ability(Abilities.EMBODY_ASPECT_WELLSPRING, 9) .attr(PostBattleInitStatChangeAbAttr, BattleStat.SPDEF, 1, true) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr), - new Ability(Abilities.EMBODY_ASPECT_HEARTHFLAME, "Embody Aspect", "The Pokémon's heart fills with memories, causing the Hearthflame Mask to shine and the Pokémon's Attack stat to be boosted.", 9) + new Ability(Abilities.EMBODY_ASPECT_HEARTHFLAME, 9) .attr(PostBattleInitStatChangeAbAttr, BattleStat.ATK, 1, true) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr), - new Ability(Abilities.EMBODY_ASPECT_CORNERSTONE, "Embody Aspect", "The Pokémon's heart fills with memories, causing the Cornerstone Mask to shine and the Pokémon's Defense stat to be boosted.", 9) + new Ability(Abilities.EMBODY_ASPECT_CORNERSTONE, 9) .attr(PostBattleInitStatChangeAbAttr, BattleStat.DEF, 1, true) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr), - new Ability(Abilities.TERA_SHIFT, "Tera Shift", "When the Pokémon enters a battle, it absorbs the energy around itself and transforms into its Terastal Form.", 9) + new Ability(Abilities.TERA_SHIFT, 9) .attr(PostSummonFormChangeAbAttr, p => p.getFormKey() ? 0 : 1) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) .attr(NoFusionAbilityAbAttr), - new Ability(Abilities.TERA_SHELL, "Tera Shell (N)", "The Pokémon's shell contains the powers of each type. All damage-dealing moves that hit the Pokémon when its HP is full will not be very effective.", 9) + new Ability(Abilities.TERA_SHELL, 9) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) - .ignorable(), - new Ability(Abilities.TERAFORM_ZERO, "Teraform Zero (N)", "When Terapagos changes into its Stellar Form, it uses its hidden powers to eliminate all effects of weather and terrain, reducing them to zero.", 9) - .attr(UncopiableAbilityAbAttr) - .attr(UnswappableAbilityAbAttr), - new Ability(Abilities.POISON_PUPPETEER, "Poison Puppeteer (N)", "Pokémon poisoned by Pecharunt's moves will also become confused.", 9) + .ignorable() + .unimplemented(), + new Ability(Abilities.TERAFORM_ZERO, 9) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) + .unimplemented(), + new Ability(Abilities.POISON_PUPPETEER, 9) + .attr(UncopiableAbilityAbAttr) + .attr(UnswappableAbilityAbAttr) + .unimplemented(), ); } diff --git a/src/locales/en/ability.ts b/src/locales/en/ability.ts new file mode 100644 index 00000000000..8360c0c08b6 --- /dev/null +++ b/src/locales/en/ability.ts @@ -0,0 +1,1244 @@ +import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; + +export const ability: AbilityTranslationEntries = { + stench: { + name: "Stench", + description: "By releasing stench when attacking, this Pokémon may cause the target to flinch.", + }, + drizzle: { + name: "Drizzle", + description: "The Pokémon makes it rain when it enters a battle.", + }, + speedBoost: { + name: "Speed Boost", + description: "Its Speed stat is boosted every turn.", + }, + battleArmor: { + name: "Battle Armor", + description: "Hard armor protects the Pokémon from critical hits.", + }, + sturdy: { + name: "Sturdy", + description: "It cannot be knocked out with one hit. One-hit KO moves cannot knock it out, either.", + }, + damp: { + name: "Damp", + description: "Prevents the use of explosive moves, such as Self-Destruct, by dampening its surroundings.", + }, + limber: { + name: "Limber", + description: "Its limber body protects the Pokémon from paralysis.", + }, + sandVeil: { + name: "Sand Veil", + description: "Boosts the Pokémon's evasiveness in a sandstorm.", + }, + static: { + name: "Static", + description: "The Pokémon is charged with static electricity, so contact with it may cause paralysis.", + }, + voltAbsorb: { + name: "Volt Absorb", + description: "Restores HP if hit by an Electric-type move instead of taking damage.", + }, + waterAbsorb: { + name: "Water Absorb", + description: "Restores HP if hit by a Water-type move instead of taking damage.", + }, + oblivious: { + name: "Oblivious", + description: "The Pokémon is oblivious, and that keeps it from being infatuated or falling for taunts.", + }, + cloudNine: { + name: "Cloud Nine", + description: "Eliminates the effects of weather.", + }, + compoundEyes: { + name: "Compound Eyes", + description: "The Pokémon's compound eyes boost its accuracy.", + }, + insomnia: { + name: "Insomnia", + description: "The Pokémon is suffering from insomnia and cannot fall asleep.", + }, + colorChange: { + name: "Color Change", + description: "The Pokémon's type becomes the type of the move used on it.", + }, + immunity: { + name: "Immunity", + description: "The immune system of the Pokémon prevents it from getting poisoned.", + }, + flashFire: { + name: "Flash Fire", + description: "Powers up the Pokémon's Fire-type moves if it's hit by one.", + }, + shieldDust: { + name: "Shield Dust", + description: "This Pokémon's dust blocks the additional effects of attacks taken.", + }, + ownTempo: { + name: "Own Tempo", + description: "This Pokémon has its own tempo, and that prevents it from becoming confused.", + }, + suctionCups: { + name: "Suction Cups", + description: "This Pokémon uses suction cups to stay in one spot to negate all moves and items that force switching out.", + }, + intimidate: { + name: "Intimidate", + description: "The Pokémon intimidates opposing Pokémon upon entering battle, lowering their Attack stat.", + }, + shadowTag: { + name: "Shadow Tag", + description: "This Pokémon steps on the opposing Pokémon's shadow to prevent it from escaping.", + }, + roughSkin: { + name: "Rough Skin", + description: "This Pokémon inflicts damage with its rough skin to the attacker on contact.", + }, + wonderGuard: { + name: "Wonder Guard", + description: "Its mysterious power only lets supereffective moves hit the Pokémon.", + }, + levitate: { + name: "Levitate", + description: "By floating in the air, the Pokémon receives full immunity to all Ground-type moves.", + }, + effectSpore: { + name: "Effect Spore", + description: "Contact with the Pokémon may inflict poison, sleep, or paralysis on its attacker.", + }, + synchronize: { + name: "Synchronize", + description: "The attacker will receive the same status condition if it inflicts a burn, poison, or paralysis to the Pokémon.", + }, + clearBody: { + name: "Clear Body", + description: "Prevents other Pokémon's moves or Abilities from lowering the Pokémon's stats.", + }, + naturalCure: { + name: "Natural Cure", + description: "All status conditions heal when the Pokémon switches out.", + }, + lightningRod: { + name: "Lightning Rod", + description: "The Pokémon draws in all Electric-type moves. Instead of being hit by Electric-type moves, it boosts its Sp. Atk.", + }, + sereneGrace: { + name: "Serene Grace", + description: "Boosts the likelihood of additional effects occurring when attacking.", + }, + swiftSwim: { + name: "Swift Swim", + description: "Boosts the Pokémon's Speed stat in rain.", + }, + chlorophyll: { + name: "Chlorophyll", + description: "Boosts the Pokémon's Speed stat in harsh sunlight.", + }, + illuminate: { + name: "Illuminate", + description: "By illuminating its surroundings, the Pokémon raises the likelihood of meeting wild Pokémon and prevents its accuracy from being lowered.", + }, + trace: { + name: "Trace", + description: "When it enters a battle, the Pokémon copies an opposing Pokémon's Ability.", + }, + hugePower: { + name: "Huge Power", + description: "Doubles the Pokémon's Attack stat.", + }, + poisonPoint: { + name: "Poison Point", + description: "Contact with the Pokémon may poison the attacker.", + }, + innerFocus: { + name: "Inner Focus", + description: "The Pokémon's intensely focused, and that protects the Pokémon from flinching.", + }, + magmaArmor: { + name: "Magma Armor", + description: "The Pokémon is covered with hot magma, which prevents the Pokémon from becoming frozen.", + }, + waterVeil: { + name: "Water Veil", + description: "The Pokémon is covered with a water veil, which prevents the Pokémon from getting a burn.", + }, + magnetPull: { + name: "Magnet Pull", + description: "Prevents Steel-type Pokémon from escaping using its magnetic force.", + }, + soundproof: { + name: "Soundproof", + description: "Soundproofing gives the Pokémon full immunity to all sound-based moves.", + }, + rainDish: { + name: "Rain Dish", + description: "The Pokémon gradually regains HP in rain.", + }, + sandStream: { + name: "Sand Stream", + description: "The Pokémon summons a sandstorm when it enters a battle.", + }, + pressure: { + name: "Pressure", + description: "By putting pressure on the opposing Pokémon, it raises their PP usage.", + }, + thickFat: { + name: "Thick Fat", + description: "The Pokémon is protected by a layer of thick fat, which halves the damage taken from Fire- and Ice-type moves.", + }, + earlyBird: { + name: "Early Bird", + description: "The Pokémon awakens from sleep twice as fast as other Pokémon.", + }, + flameBody: { + name: "Flame Body", + description: "Contact with the Pokémon may burn the attacker.", + }, + runAway: { + name: "Run Away", + description: "Enables a sure getaway from wild Pokémon.", + }, + keenEye: { + name: "Keen Eye", + description: "Keen eyes prevent other Pokémon from lowering this Pokémon's accuracy.", + }, + hyperCutter: { + name: "Hyper Cutter", + description: "The Pokémon's proud of its powerful pincers. They prevent other Pokémon from lowering its Attack stat.", + }, + pickup: { + name: "Pickup", + description: "The Pokémon may pick up the item an opposing Pokémon held during a battle.", + }, + truant: { + name: "Truant", + description: "The Pokémon can't use a move if it had used a move on the previous turn.", + }, + hustle: { + name: "Hustle", + description: "Boosts the Attack stat, but lowers accuracy.", + }, + cuteCharm: { + name: "Cute Charm", + description: "Contact with the Pokémon may cause infatuation.", + }, + plus: { + name: "Plus", + description: "Boosts the Sp. Atk stat of the Pokémon if an ally with the Plus or Minus Ability is also in battle.", + }, + minus: { + name: "Minus", + description: "Boosts the Sp. Atk stat of the Pokémon if an ally with the Plus or Minus Ability is also in battle.", + }, + forecast: { + name: "Forecast", + description: "The Pokémon transforms with the weather to change its type to Water, Fire, or Ice.", + }, + stickyHold: { + name: "Sticky Hold", + description: "Items held by the Pokémon are stuck fast and cannot be removed by other Pokémon.", + }, + shedSkin: { + name: "Shed Skin", + description: "The Pokémon may heal its own status conditions by shedding its skin.", + }, + guts: { + name: "Guts", + description: "It's so gutsy that having a status condition boosts the Pokémon's Attack stat.", + }, + marvelScale: { + name: "Marvel Scale", + description: "The Pokémon's marvelous scales boost the Defense stat if it has a status condition.", + }, + liquidOoze: { + name: "Liquid Ooze", + description: "The oozed liquid has a strong stench, which damages attackers using any draining move.", + }, + overgrow: { + name: "Overgrow", + description: "Powers up Grass-type moves when the Pokémon's HP is low.", + }, + blaze: { + name: "Blaze", + description: "Powers up Fire-type moves when the Pokémon's HP is low.", + }, + torrent: { + name: "Torrent", + description: "Powers up Water-type moves when the Pokémon's HP is low.", + }, + swarm: { + name: "Swarm", + description: "Powers up Bug-type moves when the Pokémon's HP is low.", + }, + rockHead: { + name: "Rock Head", + description: "Protects the Pokémon from recoil damage.", + }, + drought: { + name: "Drought", + description: "Turns the sunlight harsh when the Pokémon enters a battle.", + }, + arenaTrap: { + name: "Arena Trap", + description: "Prevents opposing Pokémon from fleeing.", + }, + vitalSpirit: { + name: "Vital Spirit", + description: "The Pokémon is full of vitality, and that prevents it from falling asleep.", + }, + whiteSmoke: { + name: "White Smoke", + description: "The Pokémon is protected by its white smoke, which prevents other Pokémon from lowering its stats.", + }, + purePower: { + name: "Pure Power", + description: "Using its pure power, the Pokémon doubles its Attack stat.", + }, + shellArmor: { + name: "Shell Armor", + description: "A hard shell protects the Pokémon from critical hits.", + }, + airLock: { + name: "Air Lock", + description: "Eliminates the effects of weather.", + }, + tangledFeet: { + name: "Tangled Feet", + description: "Raises evasiveness if the Pokémon is confused.", + }, + motorDrive: { + name: "Motor Drive", + description: "Boosts its Speed stat if hit by an Electric-type move instead of taking damage.", + }, + rivalry: { + name: "Rivalry", + description: "Becomes competitive and deals more damage to Pokémon of the same gender, but deals less to Pokémon of the opposite gender.", + }, + steadfast: { + name: "Steadfast", + description: "The Pokémon's determination boosts the Speed stat each time the Pokémon flinches.", + }, + snowCloak: { + name: "Snow Cloak", + description: "Boosts the Pokémon's evasiveness in snow.", + }, + gluttony: { + name: "Gluttony", + description: "Makes the Pokémon eat a held Berry when its HP drops to half or less, which is sooner than usual.", + }, + angerPoint: { + name: "Anger Point", + description: "The Pokémon is angered when it takes a critical hit, and that maxes its Attack stat.", + }, + unburden: { + name: "Unburden", + description: "Boosts the Speed stat if the Pokémon's held item is used or lost.", + }, + heatproof: { + name: "Heatproof", + description: "The heatproof body of the Pokémon halves the damage from Fire-type moves that hit it.", + }, + simple: { + name: "Simple", + description: "The stat changes the Pokémon receives are doubled.", + }, + drySkin: { + name: "Dry Skin", + description: "Restores HP in rain or when hit by Water-type moves. Reduces HP in harsh sunlight, and increases the damage received from Fire-type moves.", + }, + download: { + name: "Download", + description: "Compares an opposing Pokémon's Defense and Sp. Def stats before raising its own Attack or Sp. Atk stat—whichever will be more effective.", + }, + ironFist: { + name: "Iron Fist", + description: "Powers up punching moves.", + }, + poisonHeal: { + name: "Poison Heal", + description: "Restores HP if the Pokémon is poisoned instead of losing HP.", + }, + adaptability: { + name: "Adaptability", + description: "Powers up moves of the same type as the Pokémon.", + }, + skillLink: { + name: "Skill Link", + description: "Maximizes the number of times multistrike moves hit.", + }, + hydration: { + name: "Hydration", + description: "Heals status conditions if it's raining.", + }, + solarPower: { + name: "Solar Power", + description: "Boosts the Sp. Atk stat in harsh sunlight, but HP decreases every turn.", + }, + quickFeet: { + name: "Quick Feet", + description: "Boosts the Speed stat if the Pokémon has a status condition.", + }, + normalize: { + name: "Normalize", + description: "All the Pokémon's moves become Normal type. The power of those moves is boosted a little.", + }, + sniper: { + name: "Sniper", + description: "Powers up moves if they become critical hits when attacking.", + }, + magicGuard: { + name: "Magic Guard", + description: "The Pokémon only takes damage from attacks.", + }, + noGuard: { + name: "No Guard", + description: "The Pokémon employs no-guard tactics to ensure incoming and outgoing attacks always land.", + }, + stall: { + name: "Stall", + description: "The Pokémon moves after all other Pokémon do.", + }, + technician: { + name: "Technician", + description: "Powers up the Pokémon's weaker moves.", + }, + leafGuard: { + name: "Leaf Guard", + description: "Prevents status conditions in harsh sunlight.", + }, + klutz: { + name: "Klutz", + description: "The Pokémon can't use any held items.", + }, + moldBreaker: { + name: "Mold Breaker", + description: "Moves can be used on the target regardless of its Abilities.", + }, + superLuck: { + name: "Super Luck", + description: "The Pokémon is so lucky that the critical-hit ratios of its moves are boosted.", + }, + aftermath: { + name: "Aftermath", + description: "Damages the attacker if it contacts the Pokémon with a finishing hit.", + }, + anticipation: { + name: "Anticipation", + description: "The Pokémon can sense an opposing Pokémon's dangerous moves.", + }, + forewarn: { + name: "Forewarn", + description: "When it enters a battle, the Pokémon can tell one of the moves an opposing Pokémon has.", + }, + unaware: { + name: "Unaware", + description: "When attacking, the Pokémon ignores the target Pokémon's stat changes.", + }, + tintedLens: { + name: "Tinted Lens", + description: 'The Pokémon can use "not very effective" moves to deal regular damage.', + }, + filter: { + name: "Filter", + description: "Reduces the power of supereffective attacks taken.", + }, + slowStart: { + name: "Slow Start", + description: "For five turns, the Pokémon's Attack and Speed stats are halved.", + }, + scrappy: { + name: "Scrappy", + description: "The Pokémon can hit Ghost-type Pokémon with Normal- and Fighting-type moves.", + }, + stormDrain: { + name: "Storm Drain", + description: "Draws in all Water-type moves. Instead of being hit by Water-type moves, it boosts its Sp. Atk.", + }, + iceBody: { + name: "Ice Body", + description: "The Pokémon gradually regains HP in snow.", + }, + solidRock: { + name: "Solid Rock", + description: "Reduces the power of supereffective attacks taken.", + }, + snowWarning: { + name: "Snow Warning", + description: "The Pokémon makes it snow when it enters a battle.", + }, + honeyGather: { + name: "Honey Gather", + description: "The Pokémon may gather Honey after a battle.", + }, + frisk: { + name: "Frisk", + description: "When it enters a battle, the Pokémon can check an opposing Pokémon's held item.", + }, + reckless: { + name: "Reckless", + description: "Powers up moves that have recoil damage.", + }, + multitype: { + name: "Multitype", + description: "Changes the Pokémon's type to match the Plate or Z-Crystal it holds.", + }, + flowerGift: { + name: "Flower Gift", + description: "Boosts the Attack and Sp. Def stats of itself and allies in harsh sunlight.", + }, + badDreams: { + name: "Bad Dreams", + description: "Reduces the HP of sleeping opposing Pokémon.", + }, + pickpocket: { + name: "Pickpocket", + description: "Steals an item from an attacker that made direct contact.", + }, + sheerForce: { + name: "Sheer Force", + description: "Removes additional effects to increase the power of moves when attacking.", + }, + contrary: { + name: "Contrary", + description: "Makes stat changes have an opposite effect.", + }, + unnerve: { + name: "Unnerve", + description: "Unnerves opposing Pokémon and makes them unable to eat Berries.", + }, + defiant: { + name: "Defiant", + description: "Boosts the Pokémon's Attack stat sharply when its stats are lowered.", + }, + defeatist: { + name: "Defeatist", + description: "Halves the Pokémon's Attack and Sp. Atk stats when its HP becomes half or less.", + }, + cursedBody: { + name: "Cursed Body", + description: "May disable a move used on the Pokémon.", + }, + healer: { + name: "Healer", + description: "Sometimes heals an ally's status condition.", + }, + friendGuard: { + name: "Friend Guard", + description: "Reduces damage done to allies.", + }, + weakArmor: { + name: "Weak Armor", + description: "Physical attacks to the Pokémon lower its Defense stat but sharply raise its Speed stat.", + }, + heavyMetal: { + name: "Heavy Metal", + description: "Doubles the Pokémon's weight.", + }, + lightMetal: { + name: "Light Metal", + description: "Halves the Pokémon's weight.", + }, + multiscale: { + name: "Multiscale", + description: "Reduces the amount of damage the Pokémon takes while its HP is full.", + }, + toxicBoost: { + name: "Toxic Boost", + description: "Powers up physical attacks when the Pokémon is poisoned.", + }, + flareBoost: { + name: "Flare Boost", + description: "Powers up special attacks when the Pokémon is burned.", + }, + harvest: { + name: "Harvest", + description: "May create another Berry after one is used.", + }, + telepathy: { + name: "Telepathy", + description: "Anticipates an ally's attack and dodges it.", + }, + moody: { + name: "Moody", + description: "Raises one stat sharply and lowers another every turn.", + }, + overcoat: { + name: "Overcoat", + description: "Protects the Pokémon from things like sand, hail, and powder.", + }, + poisonTouch: { + name: "Poison Touch", + description: "May poison a target when the Pokémon makes contact.", + }, + regenerator: { + name: "Regenerator", + description: "Restores a little HP when withdrawn from battle.", + }, + bigPecks: { + name: "Big Pecks", + description: "Protects the Pokémon from Defense-lowering effects.", + }, + sandRush: { + name: "Sand Rush", + description: "Boosts the Pokémon's Speed stat in a sandstorm.", + }, + wonderSkin: { + name: "Wonder Skin", + description: "Makes status moves more likely to miss.", + }, + analytic: { + name: "Analytic", + description: "Boosts move power when the Pokémon moves last.", + }, + illusion: { + name: "Illusion", + description: "Comes out disguised as the Pokémon in the party's last spot.", + }, + imposter: { + name: "Imposter", + description: "The Pokémon transforms itself into the Pokémon it's facing.", + }, + infiltrator: { + name: "Infiltrator", + description: "Passes through the opposing Pokémon's barrier, substitute, and the like and strikes.", + }, + mummy: { + name: "Mummy", + description: "Contact with the Pokémon changes the attacker's Ability to Mummy.", + }, + moxie: { + name: "Moxie", + description: "The Pokémon shows moxie, and that boosts the Attack stat after knocking out any Pokémon.", + }, + justified: { + name: "Justified", + description: "Being hit by a Dark-type move boosts the Attack stat of the Pokémon, for justice.", + }, + rattled: { + name: "Rattled", + description: "Intimidate or being hit by a Dark-, Ghost-, or Bug-type move will scare the Pokémon and boost its Speed stat.", + }, + magicBounce: { + name: "Magic Bounce", + description: "Reflects status moves instead of getting hit by them.", + }, + sapSipper: { + name: "Sap Sipper", + description: "Boosts the Attack stat if hit by a Grass-type move instead of taking damage.", + }, + prankster: { + name: "Prankster", + description: "Gives priority to a status move.", + }, + sandForce: { + name: "Sand Force", + description: "Boosts the power of Rock-, Ground-, and Steel-type moves in a sandstorm.", + }, + ironBarbs: { + name: "Iron Barbs", + description: "Inflicts damage on the attacker upon contact with iron barbs.", + }, + zenMode: { + name: "Zen Mode", + description: "Changes the Pokémon's shape when HP is half or less.", + }, + victoryStar: { + name: "Victory Star", + description: "Boosts the accuracy of its allies and itself.", + }, + turboblaze: { + name: "Turboblaze", + description: "Moves can be used on the target regardless of its Abilities.", + }, + teravolt: { + name: "Teravolt", + description: "Moves can be used on the target regardless of its Abilities.", + }, + aromaVeil: { + name: "Aroma Veil", + description: "Protects itself and its allies from attacks that limit their move choices.", + }, + flowerVeil: { + name: "Flower Veil", + description: "Ally Grass-type Pokémon are protected from status conditions and the lowering of their stats.", + }, + cheekPouch: { + name: "Cheek Pouch", + description: "Restores HP as well when the Pokémon eats a Berry.", + }, + protean: { + name: "Protean", + description: "Changes the Pokémon's type to the type of the move it's about to use.", + }, + furCoat: { + name: "Fur Coat", + description: "Halves the damage from physical moves.", + }, + magician: { + name: "Magician", + description: "The Pokémon steals the held item of a Pokémon it hits with a move.", + }, + bulletproof: { + name: "Bulletproof", + description: "Protects the Pokémon from some ball and bomb moves.", + }, + competitive: { + name: "Competitive", + description: "Boosts the Sp. Atk stat sharply when a stat is lowered.", + }, + strongJaw: { + name: "Strong Jaw", + description: "The Pokémon's strong jaw boosts the power of its biting moves.", + }, + refrigerate: { + name: "Refrigerate", + description: "Normal-type moves become Ice-type moves. The power of those moves is boosted a little.", + }, + sweetVeil: { + name: "Sweet Veil", + description: "Prevents itself and ally Pokémon from falling asleep.", + }, + stanceChange: { + name: "Stance Change", + description: "The Pokémon changes its form to Blade Forme when it uses an attack move and changes to Shield Forme when it uses King's Shield.", + }, + galeWings: { + name: "Gale Wings", + description: "Gives priority to Flying-type moves when the Pokémon's HP is full.", + }, + megaLauncher: { + name: "Mega Launcher", + description: "Powers up aura and pulse moves.", + }, + grassPelt: { + name: "Grass Pelt", + description: "Boosts the Pokémon's Defense stat on Grassy Terrain.", + }, + symbiosis: { + name: "Symbiosis", + description: "The Pokémon passes its item to an ally that has used up an item.", + }, + toughClaws: { + name: "Tough Claws", + description: "Powers up moves that make direct contact.", + }, + pixilate: { + name: "Pixilate", + description: "Normal-type moves become Fairy-type moves. The power of those moves is boosted a little.", + }, + gooey: { + name: "Gooey", + description: "Contact with the Pokémon lowers the attacker's Speed stat.", + }, + aerilate: { + name: "Aerilate", + description: "Normal-type moves become Flying-type moves. The power of those moves is boosted a little.", + }, + parentalBond: { + name: "Parental Bond", + description: "Parent and child each attacks.", + }, + darkAura: { + name: "Dark Aura", + description: "Powers up each Pokémon's Dark-type moves.", + }, + fairyAura: { + name: "Fairy Aura", + description: "Powers up each Pokémon's Fairy-type moves.", + }, + auraBreak: { + name: "Aura Break", + description: 'The effects of "Aura" Abilities are reversed to lower the power of affected moves.', + }, + primordialSea: { + name: "Primordial Sea", + description: "The Pokémon changes the weather to nullify Fire-type attacks.", + }, + desolateLand: { + name: "Desolate Land", + description: "The Pokémon changes the weather to nullify Water-type attacks.", + }, + deltaStream: { + name: "Delta Stream", + description: "The Pokémon changes the weather to eliminate all of the Flying type's weaknesses.", + }, + stamina: { + name: "Stamina", + description: "Boosts the Defense stat when hit by an attack.", + }, + wimpOut: { + name: "Wimp Out", + description: "The Pokémon cowardly switches out when its HP becomes half or less.", + }, + emergencyExit: { + name: "Emergency Exit", + description: "The Pokémon, sensing danger, switches out when its HP becomes half or less.", + }, + waterCompaction: { + name: "Water Compaction", + description: "Boosts the Pokémon's Defense stat sharply when hit by a Water-type move.", + }, + merciless: { + name: "Merciless", + description: "The Pokémon's attacks become critical hits if the target is poisoned.", + }, + shieldsDown: { + name: "Shields Down", + description: "When its HP becomes half or less, the Pokémon's shell breaks and it becomes aggressive.", + }, + stakeout: { + name: "Stakeout", + description: "Doubles the damage dealt to the target's replacement if the target switches out.", + }, + waterBubble: { + name: "Water Bubble", + description: "Lowers the power of Fire-type moves done to the Pokémon and prevents the Pokémon from getting a burn.", + }, + steelworker: { + name: "Steelworker", + description: "Powers up Steel-type moves.", + }, + berserk: { + name: "Berserk", + description: "Boosts the Pokémon's Sp. Atk stat when it takes a hit that causes its HP to become half or less.", + }, + slushRush: { + name: "Slush Rush", + description: "Boosts the Pokémon's Speed stat in snow.", + }, + longReach: { + name: "Long Reach", + description: "The Pokémon uses its moves without making contact with the target.", + }, + liquidVoice: { + name: "Liquid Voice", + description: "All sound-based moves become Water-type moves.", + }, + triage: { + name: "Triage", + description: "Gives priority to a healing move.", + }, + galvanize: { + name: "Galvanize", + description: "Normal-type moves become Electric-type moves. The power of those moves is boosted a little.", + }, + surgeSurfer: { + name: "Surge Surfer", + description: "Doubles the Pokémon's Speed stat on Electric Terrain.", + }, + schooling: { + name: "Schooling", + description: "When it has a lot of HP, the Pokémon forms a powerful school. It stops schooling when its HP is low.", + }, + disguise: { + name: "Disguise", + description: "Once per battle, the shroud that covers the Pokémon can protect it from an attack.", + }, + battleBond: { + name: "Battle Bond", + description: "Defeating an opposing Pokémon strengthens the Pokémon's bond with its Trainer, and it becomes Ash-Greninja. Water Shuriken gets more powerful.", + }, + powerConstruct: { + name: "Power Construct", + description: "Other Cells gather to aid when its HP becomes half or less. Then the Pokémon changes its form to Complete Forme.", + }, + corrosion: { + name: "Corrosion", + description: "The Pokémon can poison the target even if it's a Steel or Poison type.", + }, + comatose: { + name: "Comatose", + description: "It's always drowsing and will never wake up. It can attack without waking up.", + }, + queenlyMajesty: { + name: "Queenly Majesty", + description: "Its majesty pressures the opposing Pokémon, making it unable to attack using priority moves.", + }, + innardsOut: { + name: "Innards Out", + description: "Damages the attacker landing the finishing hit by the amount equal to its last HP.", + }, + dancer: { + name: "Dancer", + description: "When another Pokémon uses a dance move, it can use a dance move following it regardless of its Speed.", + }, + battery: { + name: "Battery", + description: "Powers up ally Pokémon's special moves.", + }, + fluffy: { + name: "Fluffy", + description: "Halves the damage taken from moves that make direct contact, but doubles that of Fire-type moves.", + }, + dazzling: { + name: "Dazzling", + description: "Surprises the opposing Pokémon, making it unable to attack using priority moves.", + }, + soulHeart: { + name: "Soul-Heart", + description: "Boosts its Sp. Atk stat every time a Pokémon faints.", + }, + tanglingHair: { + name: "Tangling Hair", + description: "Contact with the Pokémon lowers the attacker's Speed stat.", + }, + receiver: { + name: "Receiver", + description: "The Pokémon copies the Ability of a defeated ally.", + }, + powerOfAlchemy: { + name: "Power of Alchemy", + description: "The Pokémon copies the Ability of a defeated ally.", + }, + beastBoost: { + name: "Beast Boost", + description: "The Pokémon boosts its most proficient stat each time it knocks out a Pokémon.", + }, + rksSystem: { + name: "RKS System", + description: "Changes the Pokémon's type to match the memory disc it holds.", + }, + electricSurge: { + name: "Electric Surge", + description: "Turns the ground into Electric Terrain when the Pokémon enters a battle.", + }, + psychicSurge: { + name: "Psychic Surge", + description: "Turns the ground into Psychic Terrain when the Pokémon enters a battle.", + }, + mistySurge: { + name: "Misty Surge", + description: "Turns the ground into Misty Terrain when the Pokémon enters a battle.", + }, + grassySurge: { + name: "Grassy Surge", + description: "Turns the ground into Grassy Terrain when the Pokémon enters a battle.", + }, + fullMetalBody: { + name: "Full Metal Body", + description: "Prevents other Pokémon's moves or Abilities from lowering the Pokémon's stats.", + }, + shadowShield: { + name: "Shadow Shield", + description: "Reduces the amount of damage the Pokémon takes while its HP is full.", + }, + prismArmor: { + name: "Prism Armor", + description: "Reduces the power of supereffective attacks taken.", + }, + neuroforce: { + name: "Neuroforce", + description: "Powers up moves that are super effective.", + }, + intrepidSword: { + name: "Intrepid Sword", + description: "Boosts the Pokémon's Attack stat when the Pokémon enters a battle.", + }, + dauntlessShield: { + name: "Dauntless Shield", + description: "Boosts the Pokémon's Defense stat when the Pokémon enters a battle.", + }, + libero: { + name: "Libero", + description: "Changes the Pokémon's type to the type of the move it's about to use.", + }, + ballFetch: { + name: "Ball Fetch", + description: "The Pokémon will fetch the Poké Ball from the first failed throw of the battle.", + }, + cottonDown: { + name: "Cotton Down", + description: "When the Pokémon is hit by an attack, it scatters cotton fluff around and lowers the Speed stat of all Pokémon except itself.", + }, + propellerTail: { + name: "Propeller Tail", + description: "Ignores the effects of opposing Pokémon's Abilities and moves that draw in moves.", + }, + mirrorArmor: { + name: "Mirror Armor", + description: "Bounces back only the stat-lowering effects that the Pokémon receives.", + }, + gulpMissile: { + name: "Gulp Missile", + description: "When the Pokémon uses Surf or Dive, it will come back with prey. When it takes damage, it will spit out the prey to attack.", + }, + stalwart: { + name: "Stalwart", + description: "Ignores the effects of opposing Pokémon's Abilities and moves that draw in moves.", + }, + steamEngine: { + name: "Steam Engine", + description: "Boosts the Pokémon's Speed stat drastically if hit by a Fire- or Water-type move.", + }, + punkRock: { + name: "Punk Rock", + description: "Boosts the power of sound-based moves. The Pokémon also takes half the damage from these kinds of moves.", + }, + sandSpit: { + name: "Sand Spit", + description: "The Pokémon creates a sandstorm when it's hit by an attack.", + }, + iceScales: { + name: "Ice Scales", + description: "The Pokémon is protected by ice scales, which halve the damage taken from special moves.", + }, + ripen: { + name: "Ripen", + description: "Ripens Berries and doubles their effect.", + }, + iceFace: { + name: "Ice Face", + description: "The Pokémon's ice head can take a physical attack as a substitute, but the attack also changes the Pokémon's appearance. The ice will be restored when it hails.", + }, + powerSpot: { + name: "Power Spot", + description: "Just being next to the Pokémon powers up moves.", + }, + mimicry: { + name: "Mimicry", + description: "Changes the Pokémon's type depending on the terrain.", + }, + screenCleaner: { + name: "Screen Cleaner", + description: "When the Pokémon enters a battle, the effects of Light Screen, Reflect, and Aurora Veil are nullified for both opposing and ally Pokémon.", + }, + steelySpirit: { + name: "Steely Spirit", + description: "Powers up ally Pokémon's Steel-type moves.", + }, + perishBody: { + name: "Perish Body", + description: "When hit by a move that makes direct contact, the Pokémon and the attacker will faint after three turns unless they switch out of battle.", + }, + wanderingSpirit: { + name: "Wandering Spirit", + description: "The Pokémon exchanges Abilities with a Pokémon that hits it with a move that makes direct contact.", + }, + gorillaTactics: { + name: "Gorilla Tactics", + description: "Boosts the Pokémon's Attack stat but only allows the use of the first selected move.", + }, + neutralizingGas: { + name: "Neutralizing Gas", + description: "If the Pokémon with Neutralizing Gas is in the battle, the effects of all Pokémon's Abilities will be nullified or will not be triggered.", + }, + pastelVeil: { + name: "Pastel Veil", + description: "Protects the Pokémon and its ally Pokémon from being poisoned.", + }, + hungerSwitch: { + name: "Hunger Switch", + description: "The Pokémon changes its form, alternating between its Full Belly Mode and Hangry Mode after the end of each turn.", + }, + quickDraw: { + name: "Quick Draw", + description: "Enables the Pokémon to move first occasionally.", + }, + unseenFist: { + name: "Unseen Fist", + description: "If the Pokémon uses moves that make direct contact, it can attack the target even if the target protects itself.", + }, + curiousMedicine: { + name: "Curious Medicine", + description: "When the Pokémon enters a battle, it scatters medicine from its shell, which removes all stat changes from allies.", + }, + transistor: { + name: "Transistor", + description: "Powers up Electric-type moves.", + }, + dragonsMaw: { + name: "Dragon's Maw", + description: "Powers up Dragon-type moves.", + }, + chillingNeigh: { + name: "Chilling Neigh", + description: "When the Pokémon knocks out a target, it utters a chilling neigh, which boosts its Attack stat.", + }, + grimNeigh: { + name: "Grim Neigh", + description: "When the Pokémon knocks out a target, it utters a terrifying neigh, which boosts its Sp. Atk stat.", + }, + asOneGlastrier: { + name: "As One", + description: "This Ability combines the effects of both Calyrex's Unnerve Ability and Glastrier's Chilling Neigh Ability.", + }, + asOneSpectrier: { + name: "As One", + description: "This Ability combines the effects of both Calyrex's Unnerve Ability and Spectrier's Grim Neigh Ability.", + }, + lingeringAroma: { + name: "Lingering Aroma", + description: "Contact with the Pokémon changes the attacker's Ability to Lingering Aroma.", + }, + seedSower: { + name: "Seed Sower", + description: "Turns the ground into Grassy Terrain when the Pokémon is hit by an attack.", + }, + thermalExchange: { + name: "Thermal Exchange", + description: "Boosts the Attack stat when the Pokémon is hit by a Fire-type move. The Pokémon also cannot be burned.", + }, + angerShell: { + name: "Anger Shell", + description: "When an attack causes its HP to drop to half or less, the Pokémon gets angry. This lowers its Defense and Sp. Def stats but boosts its Attack, Sp. Atk, and Speed stats.", + }, + purifyingSalt: { + name: "Purifying Salt", + description: "The Pokémon's pure salt protects it from status conditions and halves the damage taken from Ghost-type moves.", + }, + wellBakedBody: { + name: "Well-Baked Body", + description: "The Pokémon takes no damage when hit by Fire-type moves. Instead, its Defense stat is sharply boosted.", + }, + windRider: { + name: "Wind Rider", + description: "Boosts the Pokémon's Attack stat if Tailwind takes effect or if the Pokémon is hit by a wind move. The Pokémon also takes no damage from wind moves.", + }, + guardDog: { + name: "Guard Dog", + description: "Boosts the Pokémon's Attack stat if intimidated. Moves and items that would force the Pokémon to switch out also fail to work.", + }, + rockyPayload: { + name: "Rocky Payload", + description: "Powers up Rock-type moves.", + }, + windPower: { + name: "Wind Power", + description: "The Pokémon becomes charged when it is hit by a wind move, boosting the power of the next Electric-type move the Pokémon uses.", + }, + zeroToHero: { + name: "Zero to Hero", + description: "The Pokémon transforms into its Hero Form when it switches out.", + }, + commander: { + name: "Commander", + description: "When the Pokémon enters a battle, it goes inside the mouth of an ally Dondozo if one is on the field. The Pokémon then issues commands from there.", + }, + electromorphosis: { + name: "Electromorphosis", + description: "The Pokémon becomes charged when it takes damage, boosting the power of the next Electric-type move the Pokémon uses.", + }, + protosynthesis: { + name: "Protosynthesis", + description: "Boosts the Pokémon's most proficient stat in harsh sunlight or if the Pokémon is holding Booster Energy.", + }, + quarkDrive: { + name: "Quark Drive", + description: "Boosts the Pokémon's most proficient stat on Electric Terrain or if the Pokémon is holding Booster Energy.", + }, + goodAsGold: { + name: "Good as Gold", + description: "A body of pure, solid gold gives the Pokémon full immunity to other Pokémon's status moves.", + }, + vesselOfRuin: { + name: "Vessel of Ruin", + description: "The power of the Pokémon's ruinous vessel lowers the Sp. Atk stats of all Pokémon except itself.", + }, + swordOfRuin: { + name: "Sword of Ruin", + description: "The power of the Pokémon's ruinous sword lowers the Defense stats of all Pokémon except itself.", + }, + tabletsOfRuin: { + name: "Tablets of Ruin", + description: "The power of the Pokémon's ruinous wooden tablets lowers the Attack stats of all Pokémon except itself.", + }, + beadsOfRuin: { + name: "Beads of Ruin", + description: "The power of the Pokémon's ruinous beads lowers the Sp. Def stats of all Pokémon except itself.", + }, + orichalcumPulse: { + name: "Orichalcum Pulse", + description: "Turns the sunlight harsh when the Pokémon enters a battle. The ancient pulse thrumming through the Pokémon also boosts its Attack stat in harsh sunlight.", + }, + hadronEngine: { + name: "Hadron Engine", + description: "Turns the ground into Electric Terrain when the Pokémon enters a battle. The futuristic engine within the Pokémon also boosts its Sp. Atk stat on Electric Terrain.", + }, + opportunist: { + name: "Opportunist", + description: "If an opponent's stat is boosted, the Pokémon seizes the opportunity to boost the same stat for itself.", + }, + cudChew: { + name: "Cud Chew", + description: "When the Pokémon eats a Berry, it will regurgitate that Berry at the end of the next turn and eat it one more time.", + }, + sharpness: { + name: "Sharpness", + description: "Powers up slicing moves.", + }, + supremeOverlord: { + name: "Supreme Overlord", + description: "When the Pokémon enters a battle, its Attack and Sp. Atk stats are slightly boosted for each of the allies in its party that have already been defeated.", + }, + costar: { + name: "Costar", + description: "When the Pokémon enters a battle, it copies an ally's stat changes.", + }, + toxicDebris: { + name: "Toxic Debris", + description: "Scatters poison spikes at the feet of the opposing team when the Pokémon takes damage from physical moves.", + }, + armorTail: { + name: "Armor Tail", + description: "The mysterious tail covering the Pokémon's head makes opponents unable to use priority moves against the Pokémon or its allies.", + }, + earthEater: { + name: "Earth Eater", + description: "If hit by a Ground-type move, the Pokémon has its HP restored instead of taking damage.", + }, + myceliumMight: { + name: "Mycelium Might", + description: "The Pokémon will always act more slowly when using status moves, but these moves will be unimpeded by the Ability of the target.", + }, + mindsEye: { + name: "Mind's Eye", + description: "The Pokémon ignores changes to opponents' evasiveness, its accuracy can't be lowered, and it can hit Ghost types with Normal- and Fighting-type moves.", + }, + supersweetSyrup: { + name: "Supersweet Syrup", + description: "A sickly sweet scent spreads across the field the first time the Pokémon enters a battle, lowering the evasiveness of opposing Pokémon.", + }, + hospitality: { + name: "Hospitality", + description: "When the Pokémon enters a battle, it showers its ally with hospitality, restoring a small amount of the ally's HP.", + }, + toxicChain: { + name: "Toxic Chain", + description: "The power of the Pokémon's toxic chain may badly poison any target the Pokémon hits with a move.", + }, + embodyAspectTeal: { + name: "Embody Aspect", + description: "The Pokémon's heart fills with memories, causing the Teal Mask to shine and the Pokémon's Speed stat to be boosted.", + }, + embodyAspectWellspring: { + name: "Embody Aspect", + description: "The Pokémon's heart fills with memories, causing the Wellspring Mask to shine and the Pokémon's Sp. Def stat to be boosted.", + }, + embodyAspectHearthflame: { + name: "Embody Aspect", + description: "The Pokémon's heart fills with memories, causing the Hearthflame Mask to shine and the Pokémon's Attack stat to be boosted.", + }, + embodyAspectCornerstone: { + name: "Embody Aspect", + description: "The Pokémon's heart fills with memories, causing the Cornerstone Mask to shine and the Pokémon's Defense stat to be boosted.", + }, + teraShift: { + name: "Tera Shift", + description: "When the Pokémon enters a battle, it absorbs the energy around itself and transforms into its Terastal Form.", + }, + teraShell: { + name: "Tera Shell", + description: "The Pokémon's shell contains the powers of each type. All damage-dealing moves that hit the Pokémon when its HP is full will not be very effective.", + }, + teraformZero: { + name: "Teraform Zero", + description: "When Terapagos changes into its Stellar Form, it uses its hidden powers to eliminate all effects of weather and terrain, reducing them to zero.", + }, + poisonPuppeteer: { + name: "Poison Puppeteer", + description: "Pokémon poisoned by Pecharunt's moves will also become confused.", + }, +} as const; diff --git a/src/locales/es/ability.ts b/src/locales/es/ability.ts new file mode 100644 index 00000000000..3010a14d62e --- /dev/null +++ b/src/locales/es/ability.ts @@ -0,0 +1,1244 @@ +import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; + +export const ability: AbilityTranslationEntries = { + "stench": { + name: "Hedor", + description: "Puede amedrentar a un Pokémon al atacarlo debido al mal olor que emana." + }, + "drizzle": { + name: "Llovizna", + description: "Hace que llueva al entrar en combate." + }, + "speedBoost": { + name: "Impulso", + description: "Aumenta su Velocidad en cada turno." + }, + "battleArmor": { + name: "Armadura Batalla", + description: "La robusta coraza que lo protege bloquea los golpes críticos." + }, + "sturdy": { + name: "Robustez", + description: "El Pokémon no puede debilitarse de un solo golpe cuando tiene los PS al máximo. También evita los movimientos fulminantes." + }, + "damp": { + name: "Humedad", + description: "Aumenta la humedad del entorno y evita que se puedan utilizar movimientos explosivos, tales como Autodestrucción." + }, + "limber": { + name: "Flexibilidad", + description: "Evita ser paralizado gracias a la flexibilidad de su cuerpo." + }, + "sandVeil": { + name: "Velo Arena", + description: "Aumenta su Evasión durante las tormentas de arena." + }, + "static": { + name: "Elec. Estática", + description: "La electricidad estática que lo envuelve puede paralizar al Pokémon que lo ataque con un movimiento de contacto." + }, + "voltAbsorb": { + name: "Absorbe Elec", + description: "Si lo alcanza un movimiento de tipo Eléctrico, recupera PS en vez de sufrir daño." + }, + "waterAbsorb": { + name: "Absorbe Agua", + description: "Si lo alcanza un movimiento de tipo Agua, recupera PS en vez de sufrir daño." + }, + "oblivious": { + name: "Despiste", + description: "Su indiferencia evita que sea provocado, caiga presa del enamoramiento o sufra los efectos de Intimidación." + }, + "cloudNine": { + name: "Aclimatación", + description: "Anula todos los efectos del tiempo atmosférico." + }, + "compoundEyes": { + name: "Ojo Compuesto", + description: "Aumenta la precisión de sus movimientos." + }, + "insomnia": { + name: "Insomnio", + description: "Su resistencia al sueño le impide quedarse dormido." + }, + "colorChange": { + name: "Cambio Color", + description: "Adopta el tipo del último movimiento del que es blanco." + }, + "immunity": { + name: "Inmunidad", + description: "Su sistema inmunitario evita el envenenamiento." + }, + "flashFire": { + name: "Absorbe Fuego", + description: "Si lo alcanza algún movimiento de tipo Fuego, potencia sus propios movimientos de dicho tipo." + }, + "shieldDust": { + name: "Polvo Escudo", + description: "El polvo de escamas que lo envuelve lo protege de los efectos secundarios de los ataques recibidos." + }, + "ownTempo": { + name: "Ritmo Propio", + description: "Como le gusta hacer las cosas a su manera, no le afecta la confusión ni sufre los efectos de Intimidación." + }, + "suctionCups": { + name: "Ventosas", + description: "Sus ventosas se aferran al suelo, con lo cual anula movimientos y objetos que fuercen el cambio de Pokémon." + }, + "intimidate": { + name: "Intimidación", + description: "Al entrar en combate, amilana al rival de tal manera que reduce su Ataque." + }, + "shadowTag": { + name: "Sombra Trampa", + description: "Pisa la sombra del rival para impedir que huya o lo cambien por otro." + }, + "roughSkin": { + name: "Piel Tosca", + description: "Hiere con su piel áspera al Pokémon que lo ataque con un movimiento de contacto." + }, + "wonderGuard": { + name: "Superguarda", + description: "Gracias a un poder misterioso, solo le hacen daño los movimientos supereficaces." + }, + "levitate": { + name: "Levitación", + description: "Su capacidad de flotar sobre el suelo le proporciona inmunidad frente a los movimientos de tipo Tierra." + }, + "effectSpore": { + name: "Efecto Espora", + description: "Puede dormir, envenenar o paralizar al Pokémon que lo ataque con un movimiento de contacto." + }, + "synchronize": { + name: "Sincronía", + description: "Contagia el envenenamiento, las quemaduras o la parálisis al Pokémon que le cause ese estado." + }, + "clearBody": { + name: "Cuerpo Puro", + description: "Evita que se reduzcan sus características a causa de movimientos o habilidades de otros Pokémon." + }, + "naturalCure": { + name: "Cura Natural", + description: "Sus problemas de estado desaparecen cuando se retira del combate." + }, + "lightningRod": { + name: "Pararrayos", + description: "Atrae y neutraliza los movimientos de tipo Eléctrico, que además le aumentan el Ataque Especial." + }, + "sereneGrace": { + name: "Dicha", + description: "Aumenta la probabilidad de que los movimientos causen efectos secundarios." + }, + "swiftSwim": { + name: "Nado Rápido", + description: "Aumenta su Velocidad cuando llueve." + }, + "chlorophyll": { + name: "Clorofila", + description: "Aumenta su Velocidad cuando hace sol." + }, + "illuminate": { + name: "Iluminación", + description: "Al iluminar el entorno, evita que su Precisión se reduzca." + }, + "trace": { + name: "Calco", + description: "Copia la habilidad del rival al entrar en combate." + }, + "hugePower": { + name: "Potencia", + description: "Duplica la potencia de sus ataques físicos." + }, + "poisonPoint": { + name: "Punto Tóxico", + description: "Puede envenenar al Pokémon que lo ataque con un movimiento de contacto." + }, + "innerFocus": { + name: "Fuerza Mental", + description: "Gracias a su profunda concentración, no se amedrenta ante los ataques de otros Pokémon ni sufre los efectos de Intimidación." + }, + "magmaArmor": { + name: "Escudo Magma", + description: "Gracias al magma candente que lo envuelve, no puede ser congelado." + }, + "waterVeil": { + name: "Velo Agua", + description: "Evita las quemaduras gracias a la capa de agua que lo envuelve." + }, + "magnetPull": { + name: "Imán", + description: "Su magnetismo atrae a los Pokémon de tipo Acero y les impide huir o ser cambiados por otros." + }, + "soundproof": { + name: "Insonorizar", + description: "Su aislamiento acústico lo protege de movimientos que usan sonido." + }, + "rainDish": { + name: "Cura Lluvia", + description: "Recupera PS de forma gradual cuando llueve." + }, + "sandStream": { + name: "Chorro Arena", + description: "Crea una tormenta de arena al entrar en combate." + }, + "pressure": { + name: "Presión", + description: "Presiona al rival de tal manera que este consume más PP al usar sus movimientos." + }, + "thickFat": { + name: "Sebo", + description: "Gracias a la gruesa capa de grasa que lo protege, reduce a la mitad el daño que recibe de ataques de tipo Fuego o Hielo." + }, + "earlyBird": { + name: "Madrugar", + description: "Si se duerme, tardará la mitad de tiempo en despertarse." + }, + "flameBody": { + name: "Cuerpo Llama", + description: "Puede quemar al Pokémon que lo ataque con un movimiento de contacto." + }, + "runAway": { + name: "Fuga", + description: "Puede escapar de cualquier Pokémon salvaje." + }, + "keenEye": { + name: "Vista Lince", + description: "Su aguda vista evita que su Precisión se reduzca." + }, + "hyperCutter": { + name: "Corte Fuerte", + description: "Evita que otros Pokémon le reduzcan el Ataque." + }, + "pickup": { + name: "Recogida", + description: "Puede recoger objetos que otros Pokémon hayan usado, o bien aquellos que encuentre en plena aventura." + }, + "truant": { + name: "Pereza", + description: "Al ejecutar un movimiento, descansará en el turno siguiente." + }, + "hustle": { + name: "Entusiasmo", + description: "Aumenta su Ataque, pero reduce su Precisión." + }, + "cuteCharm": { + name: "Gran Encanto", + description: "Puede causar enamoramiento al Pokémon que lo ataque con un movimiento de contacto." + }, + "plus": { + name: "Más", + description: "Aumenta su Ataque Especial si un Pokémon aliado tiene la habilidad Más o la habilidad Menos." + }, + "minus": { + name: "Menos", + description: "Aumenta su Ataque Especial si un Pokémon aliado tiene la habilidad Más o la habilidad Menos." + }, + "forecast": { + name: "Predicción", + description: "Cambia a tipo Agua, Fuego o Hielo en función del tiempo atmosférico." + }, + "stickyHold": { + name: "Viscosidad", + description: "Los objetos se quedan pegados a su cuerpo, por lo que no pueden robárselos." + }, + "shedSkin": { + name: "Mudar", + description: "Puede curar sus problemas de estado al mudar la piel." + }, + "guts": { + name: "Agallas", + description: "Si sufre un problema de estado, se arma de valor y aumenta su Ataque." + }, + "marvelScale": { + name: "Escama Especial", + description: "Si sufre un problema de estado, sus escamas especiales reaccionan y aumenta su Defensa." + }, + "liquidOoze": { + name: "Viscosecreción", + description: "Exuda una secreción viscosa y tóxica de intenso hedor que hiere a quienes intentan drenarle PS." + }, + "overgrow": { + name: "Espesura", + description: "Potencia sus movimientos de tipo Planta cuando le quedan pocos PS." + }, + "blaze": { + name: "Mar Llamas", + description: "Potencia sus movimientos de tipo Fuego cuando le quedan pocos PS." + }, + "torrent": { + name: "Torrente", + description: "Potencia sus movimientos de tipo Agua cuando le quedan pocos PS." + }, + "swarm": { + name: "Enjambre", + description: "Potencia sus movimientos de tipo Bicho cuando le quedan pocos PS." + }, + "rockHead": { + name: "Cabeza Roca", + description: "No pierde PS al usar movimientos que también hieren al usuario." + }, + "drought": { + name: "Sequía", + description: "El tiempo pasa a ser soleado al entrar en combate." + }, + "arenaTrap": { + name: "Trampa Arena", + description: "Evita que el rival huya o sea cambiado por otro." + }, + "vitalSpirit": { + name: "Espíritu Vital", + description: "Su determinación le impide quedarse dormido." + }, + "whiteSmoke": { + name: "Humo Blanco", + description: "El humo blanco que lo protege evita que otros Pokémon le reduzcan las características." + }, + "purePower": { + name: "Energía Pura", + description: "Duplica la potencia de sus ataques físicos gracias al yoga." + }, + "shellArmor": { + name: "Caparazón", + description: "La robusta coraza que lo protege bloquea los golpes críticos." + }, + "airLock": { + name: "Esclusa de Aire", + description: "Neutraliza todos los efectos del tiempo atmosférico." + }, + "tangledFeet": { + name: "Tumbos", + description: "Aumenta su Evasión si está confuso." + }, + "motorDrive": { + name: "Electromotor", + description: "Si lo alcanza un movimiento de tipo Eléctrico, aumenta su Velocidad en vez de sufrir daño." + }, + "rivalry": { + name: "Rivalidad", + description: "Si el objetivo es del mismo sexo, su competitividad le lleva a infligir más daño. Si es del sexo contrario, en cambio, el daño será menor." + }, + "steadfast": { + name: "Impasible", + description: "Cada vez que se amedrenta, aumenta su Velocidad debido a su voluntad inquebrantable." + }, + "snowCloak": { + name: "Manto Níveo", + description: "Aumenta su Evasión cuando nieva." + }, + "gluttony": { + name: "Gula", + description: "Cuando sus PS se ven reducidos a la mitad, engulle la baya que normalmente solo se comería cuando le quedasen pocos PS." + }, + "angerPoint": { + name: "Irascible", + description: "Si recibe un golpe crítico, monta en cólera y su Ataque aumenta al máximo." + }, + "unburden": { + name: "Liviano", + description: "Aumenta su Velocidad si usa o pierde el objeto que lleva." + }, + "heatproof": { + name: "Ignífugo", + description: "Su cuerpo, resistente al calor, reduce a la mitad el daño recibido por movimientos de tipo Fuego." + }, + "simple": { + name: "Simple", + description: "Duplica los cambios en las características." + }, + "drySkin": { + name: "Piel Seca", + description: "Pierde PS si hace sol y los recupera si llueve o recibe un movimiento de tipo Agua. Los movimientos de tipo Fuego, por su parte, le hacen más daño de lo normal." + }, + "download": { + name: "Descarga", + description: "Compara la Defensa y la Defensa Especial del rival para ver cuál es inferior y aumenta su propio Ataque o Ataque Especial según sea lo más eficaz." + }, + "ironFist": { + name: "Puño Férreo", + description: "Aumenta la potencia de los movimientos con los puños." + }, + "poisonHeal": { + name: "Antídoto", + description: "Si resulta envenenado, recupera PS en vez de perderlos." + }, + "adaptability": { + name: "Adaptable", + description: "Potencia aún más los movimientos cuyo tipo coincida con el suyo." + }, + "skillLink": { + name: "Encadenado", + description: "Ejecuta siempre los movimientos de ataque múltiple con el número máximo de golpes." + }, + "hydration": { + name: "Hidratación", + description: "Cura los problemas de estado si está lloviendo." + }, + "solarPower": { + name: "Poder Solar", + description: "Si hace sol, aumenta su Ataque Especial, pero pierde PS en cada turno." + }, + "quickFeet": { + name: "Pies Rápidos", + description: "Aumenta su Velocidad si sufre problemas de estado." + }, + "normalize": { + name: "Normalidad", + description: "Hace que todos sus movimientos se vuelvan de tipo Normal y aumenta ligeramente su potencia." + }, + "sniper": { + name: "Francotirador", + description: "Potencia los golpes críticos que asesta aún más de lo normal." + }, + "magicGuard": { + name: "Muro Mágico", + description: "Solo recibe daño de ataques." + }, + "noGuard": { + name: "Indefenso", + description: "Al quedar ambos expuestos, tanto sus movimientos como los del Pokémon que lo ataque acertarán siempre." + }, + "stall": { + name: "Rezagado", + description: "Ejecuta su movimiento tras todos los demás." + }, + "technician": { + name: "Experto", + description: "Aumenta la potencia de sus movimientos débiles." + }, + "leafGuard": { + name: "Defensa Hoja", + description: "Evita los problemas de estado si hace sol." + }, + "klutz": { + name: "Zoquete", + description: "No puede usar objetos equipados." + }, + "moldBreaker": { + name: "Rompemoldes", + description: "Sus movimientos no se ven afectados por la habilidad del objetivo." + }, + "superLuck": { + name: "Afortunado", + description: "Su buena suerte aumenta la probabilidad de asestar golpes críticos." + }, + "aftermath": { + name: "Detonación", + description: "Daña al Pokémon que le ha dado el golpe de gracia con un movimiento de contacto." + }, + "anticipation": { + name: "Anticipación", + description: "Prevé los movimientos peligrosos del rival." + }, + "forewarn": { + name: "Alerta", + description: "Revela uno de los movimientos del rival al entrar en combate." + }, + "unaware": { + name: "Ignorante", + description: "Pasa por alto los cambios en las características de un Pokémon al atacarlo o recibir daño." + }, + "tintedLens": { + name: "Cromolente", + description: "Potencia los movimientos que no son muy eficaces, que infligen ahora un daño normal." + }, + "filter": { + name: "Filtro", + description: "Mitiga el daño que le infligen los movimientos supereficaces." + }, + "slowStart": { + name: "Inicio Lento", + description: "Reduce a la mitad su Ataque y su Velocidad durante cinco turnos." + }, + "scrappy": { + name: "Intrépido", + description: "Alcanza a Pokémon de tipo Fantasma con movimientos de tipo Normal o Lucha. Además, no sufre los efectos de Intimidación." + }, + "stormDrain": { + name: "Colector", + description: "Atrae y neutraliza los movimientos de tipo Agua, que además le aumentan el Ataque Especial." + }, + "iceBody": { + name: "Gélido", + description: "Recupera PS de forma gradual cuando nieva." + }, + "solidRock": { + name: "Roca Sólida", + description: "Mitiga el daño que le infligen los movimientos supereficaces." + }, + "snowWarning": { + name: "Nevada", + description: "Invoca una nevada al entrar en combate." + }, + "honeyGather": { + name: "Recogemiel", + description: "Puede que encuentre Miel una vez concluido el combate." + }, + "frisk": { + name: "Cacheo", + description: "Puede ver el objeto que lleva el rival al entrar en combate." + }, + "reckless": { + name: "Audaz", + description: "Potencia los movimientos que también dañan al usuario." + }, + "multitype": { + name: "Multitipo", + description: "Cambia su tipo al de la tabla que lleve." + }, + "flowerGift": { + name: "Don Floral", + description: "Si hace sol, aumenta su Ataque y su Defensa Especial, así como los de sus aliados." + }, + "badDreams": { + name: "Mal Sueño", + description: "Inflige daño a cualquier rival que esté dormido." + }, + "pickpocket": { + name: "Hurto", + description: "Roba el objeto del Pokémon que lo ataque con un movimiento de contacto." + }, + "sheerForce": { + name: "Potencia Bruta", + description: "Aumenta la potencia de sus movimientos en detrimento de los efectos secundarios, que se ven anulados." + }, + "contrary": { + name: "Respondón", + description: "Invierte los cambios en las características: bajan cuando les toca subir y suben cuando les toca bajar." + }, + "unnerve": { + name: "Nerviosismo", + description: "Pone nervioso al rival y le impide comer bayas." + }, + "defiant": { + name: "Competitivo", + description: "Aumenta mucho su Ataque cuando el rival le reduce cualquiera de sus características." + }, + "defeatist": { + name: "Flaqueza", + description: "Cuando sus PS se ven reducidos a la mitad, se cansa tanto que su Ataque y su Ataque Especial también se ven reducidos a la mitad." + }, + "cursedBody": { + name: "Cuerpo Maldito", + description: "Puede anular el movimiento usado en su contra." + }, + "healer": { + name: "Alma Cura", + description: "A veces cura los problemas de estado de un aliado." + }, + "friendGuard": { + name: "Compiescolta", + description: "Reduce el daño que sufren los aliados." + }, + "weakArmor": { + name: "Armadura Frágil", + description: "Al recibir daño de un ataque físico, se reduce su Defensa, pero aumenta mucho su Velocidad." + }, + "heavyMetal": { + name: "Metal Pesado", + description: "Duplica su peso." + }, + "lightMetal": { + name: "Metal Liviano", + description: "Reduce a la mitad su peso." + }, + "multiscale": { + name: "Multiescamas", + description: "Reduce el daño que sufre si sus PS están al máximo." + }, + "toxicBoost": { + name: "Ímpetu Tóxico", + description: "Aumenta la potencia de sus ataques físicos cuando está envenenado." + }, + "flareBoost": { + name: "Ímpetu Ardiente", + description: "Aumenta la potencia de sus ataques especiales cuando sufre quemaduras." + }, + "harvest": { + name: "Cosecha", + description: "Puede reutilizar varias veces una misma baya." + }, + "telepathy": { + name: "Telepatía", + description: "Elude los ataques de los aliados durante el combate." + }, + "moody": { + name: "Veleta", + description: "Aumenta mucho una característica en cada turno, pero reduce otra." + }, + "overcoat": { + name: "Funda", + description: "No recibe daño de las tormentas de arena ni sufre los efectos causados por polvos o esporas." + }, + "poisonTouch": { + name: "Toque Tóxico", + description: "Puede envenenar al Pokémon al que ataque con un movimiento de contacto." + }, + "regenerator": { + name: "Regeneración", + description: "Recupera unos pocos PS cuando se retira del combate." + }, + "bigPecks": { + name: "Sacapecho", + description: "Impide que otros Pokémon le reduzcan la Defensa." + }, + "sandRush": { + name: "Ímpetu Arena", + description: "Aumenta su Velocidad durante las tormentas de arena." + }, + "wonderSkin": { + name: "Piel Milagro", + description: "Presenta una mayor resistencia ante los movimientos de estado." + }, + "analytic": { + name: "Cálculo Final", + description: "Aumenta la potencia de su movimiento si es el último en atacar." + }, + "illusion": { + name: "Ilusión", + description: "Adopta el aspecto del último Pokémon del equipo al entrar en combate para desconcertar al rival." + }, + "imposter": { + name: "Impostor", + description: "Se transforma en el Pokémon que tiene enfrente." + }, + "infiltrator": { + name: "Allanamiento", + description: "Ataca sorteando las barreras o el sustituto del objetivo." + }, + "mummy": { + name: "Momia", + description: "Contagia la habilidad Momia al Pokémon que lo ataque con un movimiento de contacto." + }, + "moxie": { + name: "Autoestima", + description: "Al debilitar a un objetivo, su confianza se refuerza de tal manera que aumenta su Ataque." + }, + "justified": { + name: "Justiciero", + description: "Si lo alcanza un movimiento de tipo Siniestro, aumenta el Ataque debido a su integridad." + }, + "rattled": { + name: "Cobardía", + description: "Si lo alcanza un ataque de tipo Siniestro, Bicho o Fantasma, o si sufre los efectos de Intimidación, el miedo hace que aumente su Velocidad." + }, + "magicBounce": { + name: "Espejo Mágico", + description: "Puede devolver los movimientos de estado sin verse afectado por ellos." + }, + "sapSipper": { + name: "Herbívoro", + description: "Si lo alcanza un movimiento de tipo Planta, aumenta su Ataque en vez de sufrir daño." + }, + "prankster": { + name: "Bromista", + description: "Sus movimientos de estado tienen prioridad alta." + }, + "sandForce": { + name: "Poder Arena", + description: "Potencia los movimientos de tipo Tierra, Acero y Roca durante las tormentas de arena." + }, + "ironBarbs": { + name: "Punta Acero", + description: "Inflige daño con sus púas de acero al Pokémon que lo ataque con un movimiento de contacto." + }, + "zenMode": { + name: "Modo Daruma", + description: "Cambia de forma si sus PS se ven reducidos a la mitad o menos." + }, + "victoryStar": { + name: "Tinovictoria", + description: "Aumenta su Precisión y la de sus aliados." + }, + "turboblaze": { + name: "Turbollama", + description: "Sus movimientos no se ven afectados por la habilidad del objetivo." + }, + "teravolt": { + name: "Terravoltaje", + description: "Sus movimientos no se ven afectados por la habilidad del objetivo." + }, + "aromaVeil": { + name: "Velo Aroma", + description: "Se protege a sí mismo y a sus aliados de efectos que impiden usar movimientos." + }, + "flowerVeil": { + name: "Velo Flor", + description: "Evita que los Pokémon de tipo Planta aliados sufran problemas de estado o que les reduzcan sus características." + }, + "cheekPouch": { + name: "Carrillo", + description: "Recupera PS al comer cualquier baya." + }, + "protean": { + name: "Mutatipo", + description: "Al entrar en combate, cambia su tipo al del primer movimiento que va a usar." + }, + "furCoat": { + name: "Pelaje Recio", + description: "Reduce a la mitad el daño que recibe de ataques físicos." + }, + "magician": { + name: "Prestidigitador", + description: "Roba el objeto del Pokémon al que alcance con un movimiento." + }, + "bulletproof": { + name: "Antibalas", + description: "No le afectan las bombas ni algunos proyectiles." + }, + "competitive": { + name: "Tenacidad", + description: "Aumenta mucho su Ataque Especial cuando el rival le reduce cualquiera de sus características." + }, + "strongJaw": { + name: "Mandíbula Fuerte", + description: "Su robusta mandíbula le confiere una mordedura mucho más potente." + }, + "refrigerate": { + name: "Piel Helada", + description: "Convierte los movimientos de tipo Normal en tipo Hielo y aumenta ligeramente su potencia." + }, + "sweetVeil": { + name: "Velo Dulce", + description: "No cae dormido y evita también que sus aliados se duerman." + }, + "stanceChange": { + name: "Cambio Táctico", + description: "Adopta la Forma Filo al lanzar un ataque, o bien la Forma Escudo si usa el movimiento Escudo Real." + }, + "galeWings": { + name: "Alas Vendaval", + description: "Da prioridad a los movimientos de tipo Volador si sus PS están al máximo." + }, + "megaLauncher": { + name: "Megadisparador", + description: "Aumenta la potencia de algunos movimientos de pulsos y auras." + }, + "grassPelt": { + name: "Manto Frondoso", + description: "Aumenta su Defensa si hay un campo de hierba en el terreno de combate." + }, + "symbiosis": { + name: "Simbiosis", + description: "Pasa su objeto a un aliado cuando este use el suyo." + }, + "toughClaws": { + name: "Garra Dura", + description: "Aumenta la potencia de los movimientos de contacto." + }, + "pixilate": { + name: "Piel Feérica", + description: "Convierte los movimientos de tipo Normal en tipo Hada y aumenta ligeramente su potencia." + }, + "gooey": { + name: "Baba", + description: "Reduce la Velocidad del Pokémon que lo ataque con un movimiento de contacto." + }, + "aerilate": { + name: "Piel Celeste", + description: "Convierte los movimientos de tipo Normal en tipo Volador y aumenta ligeramente su potencia." + }, + "parentalBond": { + name: "Amor Filial", + description: "Une fuerzas con su cría y ataca dos veces." + }, + "darkAura": { + name: "Aura Oscura", + description: "Aumenta la potencia de los movimientos de tipo Siniestro de todos los Pokémon." + }, + "fairyAura": { + name: "Aura Feérica", + description: "Aumenta la potencia de los movimientos de tipo Hada de todos los Pokémon." + }, + "auraBreak": { + name: "Rompeaura", + description: "Invierte los efectos de las habilidades de auras, por lo que reduce la potencia de ciertos movimientos en vez de aumentarla." + }, + "primordialSea": { + name: "Mar del Albor", + description: "Altera el clima para anular los ataques de tipo Fuego." + }, + "desolateLand": { + name: "Tierra del Ocaso", + description: "Altera el clima para anular los ataques de tipo Agua." + }, + "deltaStream": { + name: "Ráfaga Delta", + description: "Altera el clima para anular las vulnerabilidades del tipo Volador." + }, + "stamina": { + name: "Firmeza", + description: "Aumenta su Defensa al recibir un ataque." + }, + "wimpOut": { + name: "Huida", + description: "Se asusta y abandona el terreno de combate cuando sus PS se ven reducidos a la mitad." + }, + "emergencyExit": { + name: "Retirada", + description: "Abandona el terreno de combate cuando sus PS se ven reducidos a la mitad para evitar males mayores." + }, + "waterCompaction": { + name: "Hidrorrefuerzo", + description: "Aumenta mucho su Defensa si lo alcanza un movimiento de tipo Agua." + }, + "merciless": { + name: "Ensañamiento", + description: "Hace que sus movimientos asesten siempre un golpe crítico si el objetivo está envenenado." + }, + "shieldsDown": { + name: "Escudo Limitado", + description: "Rompe su coraza cuando sus PS se ven reducidos a la mitad y adopta una forma ofensiva." + }, + "stakeout": { + name: "Vigilante", + description: "Si el objetivo de su ataque es sustituido por otro, duplica el daño que infligirá." + }, + "waterBubble": { + name: "Pompa", + description: "Reduce el daño que le provocan los movimientos de tipo Fuego y es inmune a las quemaduras." + }, + "steelworker": { + name: "Acero Templado", + description: "Potencia los movimientos de tipo Acero." + }, + "berserk": { + name: "Cólera", + description: "Aumenta su Ataque Especial si sus PS se ven reducidos a la mitad debido a algún ataque." + }, + "slushRush": { + name: "Quitanieves", + description: "Aumenta su Velocidad cuando nieva." + }, + "longReach": { + name: "Remoto", + description: "Puede usar cualquier movimiento sin entrar en contacto con su objetivo." + }, + "liquidVoice": { + name: "Voz Fluida", + description: "Hace que todos sus movimientos que usan sonido pasen a ser de tipo Agua." + }, + "triage": { + name: "Primer Auxilio", + description: "Da prioridad a los movimientos que restauran PS." + }, + "galvanize": { + name: "Piel Eléctrica", + description: "Convierte los movimientos de tipo Normal en tipo Eléctrico y aumenta ligeramente su potencia." + }, + "surgeSurfer": { + name: "Cola Surf", + description: "Duplica su Velocidad si hay un campo eléctrico en el terreno de combate." + }, + "schooling": { + name: "Banco", + description: "Forma bancos con sus congéneres cuando tiene muchos PS, lo cual le otorga más fuerza. Cuando le quedan pocos PS, el banco se dispersa." + }, + "disguise": { + name: "Disfraz", + description: "Puede eludir un ataque valiéndose de la tela que le cubre el cuerpo una vez por combate." + }, + "battleBond": { + name: "Fuerte Afecto", + description: "Al derrotar a un Pokémon, los vínculos con su Entrenador se refuerzan y aumentan su Ataque, su Ataque Especial y su Velocidad." + }, + "powerConstruct": { + name: "Agrupamiento", + description: "Cuando sus PS se ven reducidos a la mitad, las células se reagrupan y adopta su Forma Completa." + }, + "corrosion": { + name: "Corrosión", + description: "Puede envenenar incluso a Pokémon de tipo Acero o Veneno." + }, + "comatose": { + name: "Letargo Perenne", + description: "No despierta jamás de su profundo letargo e incluso ataca dormido." + }, + "queenlyMajesty": { + name: "Regia Presencia", + description: "Intimida al rival y le impide usar movimientos con prioridad contra él y sus aliados." + }, + "innardsOut": { + name: "Revés", + description: "Al caer debilitado, inflige al atacante un daño equivalente a los PS que le quedaran antes de recibir el golpe de gracia." + }, + "dancer": { + name: "Pareja de Baile", + description: "Puede copiar inmediatamente cualquier movimiento de baile que haya usado otro Pokémon presente en el combate." + }, + "battery": { + name: "Batería", + description: "Potencia los ataques especiales de los aliados." + }, + "fluffy": { + name: "Peluche", + description: "Reduce a la mitad el daño recibido por los movimientos de contacto, pero duplica el que le infligen los de tipo Fuego." + }, + "dazzling": { + name: "Cuerpo Vívido", + description: "Desconcierta al rival y le impide usar movimientos con prioridad contra él y sus aliados." + }, + "soulHeart": { + name: "Coránima", + description: "Aumenta su Ataque Especial cada vez que un Pokémon cae debilitado." + }, + "tanglingHair": { + name: "Rizos Rebeldes", + description: "Reduce la Velocidad del Pokémon que lo ataque con un movimiento de contacto." + }, + "receiver": { + name: "Receptor", + description: "Adquiere la habilidad de un aliado debilitado." + }, + "powerOfAlchemy": { + name: "Reacción Química", + description: "Reacciona copiando la habilidad de un aliado debilitado." + }, + "beastBoost": { + name: "Ultraimpulso", + description: "Al derrotar a un Pokémon, aumenta su característica más fuerte." + }, + "rksSystem": { + name: "Sistema Alfa", + description: "Cambia su tipo según el disco que lleve instalado." + }, + "electricSurge": { + name: "Electrogénesis", + description: "Crea un campo eléctrico al entrar en combate." + }, + "psychicSurge": { + name: "Psicogénesis", + description: "Crea un campo psíquico al entrar en combate." + }, + "mistySurge": { + name: "Nebulogénesis", + description: "Crea un campo de niebla al entrar en combate." + }, + "grassySurge": { + name: "Herbogénesis", + description: "Crea un campo de hierba al entrar en combate." + }, + "fullMetalBody": { + name: "Guardia Metálica", + description: "Evita que se reduzcan sus características a causa de movimientos o habilidades de otros Pokémon." + }, + "shadowShield": { + name: "Guardia Espectro", + description: "Reduce el daño que sufre si sus PS están al máximo." + }, + "prismArmor": { + name: "Armadura Prisma", + description: "Mitiga el daño que le infligen los movimientos supereficaces." + }, + "neuroforce": { + name: "Fuerza Cerebral", + description: "Potencia los ataques supereficaces." + }, + "intrepidSword": { + name: "Espada Indómita", + description: "Aumenta su Ataque al entrar en combate por primera vez." + }, + "dauntlessShield": { + name: "Escudo Recio", + description: "Aumenta su Defensa al entrar en combate por primera vez." + }, + "libero": { + name: "Líbero", + description: "Al entrar en combate, cambia su tipo al del primer movimiento que va a usar." + }, + "ballFetch": { + name: "Recogebolas", + description: "Si no lleva equipado ningún objeto, recupera la Poké Ball del primer intento de captura fallido." + }, + "cottonDown": { + name: "Pelusa", + description: "Al ser alcanzado por un ataque, suelta una pelusa de algodón que reduce la Velocidad de todos los demás Pokémon." + }, + "propellerTail": { + name: "Hélice Caudal", + description: "Ignora los efectos de las habilidades o los movimientos que permiten a un Pokémon centrar la atención sobre sí." + }, + "mirrorArmor": { + name: "Coraza Reflejo", + description: "Refleja los efectos que reducen las características." + }, + "gulpMissile": { + name: "Tragamisil", + description: "Tras usar Surf o Buceo, emerge con una presa en la boca. Al recibir daño, ataca escupiéndola." + }, + "stalwart": { + name: "Acérrimo", + description: "Ignora los efectos de las habilidades o los movimientos que permiten a un Pokémon centrar la atención sobre sí." + }, + "steamEngine": { + name: "Combustible", + description: "Si lo alcanza un movimiento de tipo Fuego o Agua, aumenta muchísimo su Velocidad." + }, + "punkRock": { + name: "Punk Rock", + description: "Potencia los movimientos que usan sonido y reduce a la mitad el daño que le infligen dichos movimientos." + }, + "sandSpit": { + name: "Expulsarena", + description: "Provoca una tormenta de arena al recibir un ataque." + }, + "iceScales": { + name: "Escama de Hielo", + description: "Las gélidas escamas que protegen su cuerpo reducen a la mitad el daño que le infligen los ataques especiales." + }, + "ripen": { + name: "Maduración", + description: "Hace madurar las bayas, por lo que duplica sus efectos." + }, + "iceFace": { + name: "Cara de Hielo", + description: "Absorbe el daño de un ataque físico con el hielo de la cabeza, tras lo cual cambia de forma. El hielo se regenerará la próxima vez que nieve." + }, + "powerSpot": { + name: "Fuente Energía", + description: "Potencia los movimientos de los Pokémon adyacentes." + }, + "mimicry": { + name: "Mimetismo", + description: "Cambia su tipo según el campo que haya en el terreno de combate." + }, + "screenCleaner": { + name: "Antibarrera", + description: "Anula los efectos de Pantalla de Luz, Reflejo y Velo Aurora tanto de rivales como de aliados al entrar en combate." + }, + "steelySpirit": { + name: "Alma Acerada", + description: "Potencia los movimientos de tipo Acero del Pokémon y sus aliados." + }, + "perishBody": { + name: "Cuerpo Mortal", + description: "Si lo alcanza un movimiento de contacto, se debilitará al cabo de 3 turnos, así como el atacante, a menos que abandonen el terreno de combate." + }, + "wanderingSpirit": { + name: "Alma Errante", + description: "Si lo alcanza un movimiento de contacto, intercambia su habilidad con la del atacante." + }, + "gorillaTactics": { + name: "Monotema", + description: "Aumenta su Ataque, pero solo puede usar el primer movimiento escogido." + }, + "neutralizingGas": { + name: "Gas Reactivo", + description: "Anula los efectos de las habilidades de los demás Pokémon presentes mientras esté en el terreno de combate." + }, + "pastelVeil": { + name: "Velo Pastel", + description: "Se protege a sí mismo y a sus aliados del envenenamiento." + }, + "hungerSwitch": { + name: "Mutapetito", + description: "Alterna entre su Forma Saciada y Forma Voraz al final de cada turno." + }, + "quickDraw": { + name: "Mano Rápida", + description: "A veces, puede atacar el primero." + }, + "unseenFist": { + name: "Puño Invisible", + description: "Si usa un movimiento de contacto, puede infligir daño al objetivo aunque este se proteja." + }, + "curiousMedicine": { + name: "Medicina Extraña", + description: "Al entrar en combate, rezuma una substancia medicinal por la caracola que revierte los cambios en las características de los aliados." + }, + "transistor": { + name: "Transistor", + description: "Potencia los movimientos de tipo Eléctrico." + }, + "dragonsMaw": { + name: "Mandíbula Dragón", + description: "Potencia los movimientos de tipo Dragón." + }, + "chillingNeigh": { + name: "Relincho Blanco", + description: "Al derrotar a un objetivo, emite un relincho gélido y aumenta su Ataque." + }, + "grimNeigh": { + name: "Relincho Negro", + description: "Al derrotar a un objetivo, emite un relincho aterrador y aumenta su Ataque Especial." + }, + "asOneGlastrier": { + name: "Unidad Ecuestre", + description: "El Pokémon tiene dos habilidades: Relincho Negro de Spectrier y Nerviosismo de Calyrex." + }, + "asOneSpectrier": { + name: "Unidad Ecuestre", + description: "El Pokémon tiene dos habilidades: Relincho Negro de Spectrier y Nerviosismo de Calyrex." + }, + "lingeringAroma": { + name: "Olor Persistente", + description: "Contagia la habilidad Olor Persistente al Pokémon que lo ataque con un movimiento de contacto." + }, + "seedSower": { + name: "Disemillar", + description: "Crea un campo de hierba al recibir un ataque." + }, + "thermalExchange": { + name: "Termoconversión", + description: "Evita las quemaduras y, si lo alcanza un movimiento de tipo Fuego, aumenta su Ataque." + }, + "angerShell": { + name: "Coraza Ira", + description: "Cuando un ataque reduce sus PS a la mitad, un arrebato de cólera reduce su Defensa y su Defensa Especial, pero aumenta su Ataque, su Ataque Especial y su Velocidad." + }, + "purifyingSalt": { + name: "Sal Purificadora", + description: "Su sal pura lo protege de los problemas de estado y reduce a la mitad el daño que recibe de ataques de tipo Fantasma." + }, + "wellBakedBody": { + name: "Cuerpo Horneado", + description: "Si lo alcanza un movimiento de tipo Fuego, aumenta mucho su Defensa en vez de sufrir daño." + }, + "windRider": { + name: "Surcavientos", + description: "Si sopla un Viento Afín o lo alcanza un movimiento que usa viento, aumenta su Ataque. Tampoco recibe daño de este último." + }, + "guardDog": { + name: "Perro Guardián", + description: "Aumenta su Ataque si sufre los efectos de Intimidación. También anula movimientos y objetos que fuercen el cambio de Pokémon." + }, + "rockyPayload": { + name: "Transportarrocas", + description: "Potencia los movimientos de tipo Roca." + }, + "windPower": { + name: "Energía Eólica", + description: "Su cuerpo se carga de electricidad si lo alcanza un movimiento que usa viento, lo que potencia su siguiente movimiento de tipo Eléctrico." + }, + "zeroToHero": { + name: "Cambio Heroico", + description: "Adopta la Forma Heroica cuando se retira del combate." + }, + "commander": { + name: "Comandar", + description: "Si al entrar en combate coincide con un Dondozo aliado, se cuela en el interior de su boca para tomar el control." + }, + "electromorphosis": { + name: "Dinamo", + description: "Su cuerpo se carga de electricidad al recibir daño, lo que potencia su siguiente movimiento de tipo Eléctrico." + }, + "protosynthesis": { + name: "Paleosíntesis", + description: "Si hace sol o lleva un tanque de Energía Potenciadora, aumenta su característica más alta." + }, + "quarkDrive": { + name: "Carga Cuark", + description: "Si hay un campo eléctrico en el terreno de combate o lleva un tanque de Energía Potenciadora, aumenta su característica más alta." + }, + "goodAsGold": { + name: "Cuerpo Áureo", + description: "Su robusto cuerpo de oro inoxidable lo hace inmune frente a movimientos de estado de otros Pokémon." + }, + "vesselOfRuin": { + name: "Caldero Debacle", + description: "Reduce el Ataque Especial de todos los demás Pokémon con el poder de su caldero maldito." + }, + "swordOfRuin": { + name: "Espada Debacle", + description: "Reduce la Defensa de todos los demás Pokémon con el poder de su espada maldita." + }, + "tabletsOfRuin": { + name: "Tablilla Debacle", + description: "Reduce el Ataque de todos los demás Pokémon con el poder de sus tablillas malditas." + }, + "beadsOfRuin": { + name: "Abalorio Debacle", + description: "Reduce la Defensa Especial de todos los demás Pokémon con el poder de sus abalorios malditos." + }, + "orichalcumPulse": { + name: "Latido Oricalco", + description: "El tiempo pasa a ser soleado cuando entra en combate. Si hace mucho sol, su Ataque aumenta gracias a su pulso primigenio." + }, + "hadronEngine": { + name: "Motor Hadrónico", + description: "Crea un campo eléctrico al entrar en combate. Si hay un campo eléctrico, su Ataque Especial aumenta gracias a su motor futurista." + }, + "opportunist": { + name: "Oportunista", + description: "Copia las mejoras en las características del rival, aprovechándose de la situación." + }, + "cudChew": { + name: "Rumia", + description: "Cuando ingiere una baya, la regurgita al final del siguiente turno y se la come por segunda vez." + }, + "sharpness": { + name: "Cortante", + description: "Aumenta la potencia de los movimientos cortantes." + }, + "supremeOverlord": { + name: "General Supremo", + description: "Al entrar en combate, su Ataque y su Ataque Especial aumentan un poco por cada miembro del equipo que haya sido derrotado hasta el momento." + }, + "costar": { + name: "Unísono", + description: "Al entrar en combate, copia los cambios en las características de su aliado." + }, + "toxicDebris": { + name: "Capa Tóxica", + description: "Al recibir daño de un ataque físico, lanza una trampa de púas tóxicas a los pies del rival." + }, + "armorTail": { + name: "Cola Armadura", + description: "La extraña cola que le envuelve la cabeza impide al rival usar movimientos con prioridad contra él y sus aliados." + }, + "earthEater": { + name: "Geofagia", + description: "Si lo alcanza un movimiento de tipo Tierra, recupera PS en vez de sufrir daño." + }, + "myceliumMight": { + name: "Poder Fúngico", + description: "El Pokémon siempre actúa con lentitud cuando usa movimientos de estado, pero estos no se ven afectados por la habilidad del objetivo." + }, + "mindsEye": { + name: "Ojo Mental", + description: "Alcanza a Pokémon de tipo Fantasma con movimientos de tipo Normal o Lucha. Su Precisión no se puede reducir e ignora los cambios en la Evasión del objetivo." + }, + "supersweetSyrup": { + name: "Néctar Dulce", + description: "Al entrar en combate por primera vez, esparce un aroma dulzón a néctar que reduce la Evasión del rival." + }, + "hospitality": { + name: "Hospitalidad", + description: "Al entrar en combate, restaura algunos PS de su aliado como muestra de hospitalidad." + }, + "toxicChain": { + name: "Cadena Tóxica", + description: "Gracias al poder de su cadena impregnada de toxinas, puede envenenar gravemente al Pokémon al que ataque." + }, + "embodyAspectTeal": { + name: "Evocarrecuerdos", + description: "Al evocar viejos recuerdos, el Pokémon hace brillar la Máscara Cimiento y aumenta su Defensa." + }, + "embodyAspectWellspring": { + name: "Evocarrecuerdos", + description: "Al evocar viejos recuerdos, el Pokémon hace brillar la Máscara Cimiento y aumenta su Defensa." + }, + "embodyAspectHearthflame": { + name: "Evocarrecuerdos", + description: "Al evocar viejos recuerdos, el Pokémon hace brillar la Máscara Cimiento y aumenta su Defensa." + }, + "embodyAspectCornerstone": { + name: "Evocarrecuerdos", + description: "Al evocar viejos recuerdos, el Pokémon hace brillar la Máscara Cimiento y aumenta su Defensa." + }, + "teraShift": { + name: "Teracambio", + description: "Al entrar en combate, adopta la Forma Teracristal tras absorber la energía de su alrededor." + }, + "teraShell": { + name: "Teracaparazón", + description: "Su caparazón encierra energía de todos los tipos. Gracias a ello, si sus PS están al máximo, el movimiento que lo alcance no será muy eficaz." + }, + "teraformZero": { + name: "Teraformación 0", + description: "Cuando Terapagos adopta la Forma Astral, anula todos los efectos del tiempo atmosférico y de los campos que haya en el terreno gracias a su poder oculto." + }, + "poisonPuppeteer": { + name: "Títere Tóxico", + description: "Los rivales que Pecharunt envenene con sus movimientos también sufrirán confusión." + } +} as const; diff --git a/src/locales/fr/ability.ts b/src/locales/fr/ability.ts new file mode 100644 index 00000000000..8360c0c08b6 --- /dev/null +++ b/src/locales/fr/ability.ts @@ -0,0 +1,1244 @@ +import { AbilityTranslationEntries } from "#app/plugins/i18n.js"; + +export const ability: AbilityTranslationEntries = { + stench: { + name: "Stench", + description: "By releasing stench when attacking, this Pokémon may cause the target to flinch.", + }, + drizzle: { + name: "Drizzle", + description: "The Pokémon makes it rain when it enters a battle.", + }, + speedBoost: { + name: "Speed Boost", + description: "Its Speed stat is boosted every turn.", + }, + battleArmor: { + name: "Battle Armor", + description: "Hard armor protects the Pokémon from critical hits.", + }, + sturdy: { + name: "Sturdy", + description: "It cannot be knocked out with one hit. One-hit KO moves cannot knock it out, either.", + }, + damp: { + name: "Damp", + description: "Prevents the use of explosive moves, such as Self-Destruct, by dampening its surroundings.", + }, + limber: { + name: "Limber", + description: "Its limber body protects the Pokémon from paralysis.", + }, + sandVeil: { + name: "Sand Veil", + description: "Boosts the Pokémon's evasiveness in a sandstorm.", + }, + static: { + name: "Static", + description: "The Pokémon is charged with static electricity, so contact with it may cause paralysis.", + }, + voltAbsorb: { + name: "Volt Absorb", + description: "Restores HP if hit by an Electric-type move instead of taking damage.", + }, + waterAbsorb: { + name: "Water Absorb", + description: "Restores HP if hit by a Water-type move instead of taking damage.", + }, + oblivious: { + name: "Oblivious", + description: "The Pokémon is oblivious, and that keeps it from being infatuated or falling for taunts.", + }, + cloudNine: { + name: "Cloud Nine", + description: "Eliminates the effects of weather.", + }, + compoundEyes: { + name: "Compound Eyes", + description: "The Pokémon's compound eyes boost its accuracy.", + }, + insomnia: { + name: "Insomnia", + description: "The Pokémon is suffering from insomnia and cannot fall asleep.", + }, + colorChange: { + name: "Color Change", + description: "The Pokémon's type becomes the type of the move used on it.", + }, + immunity: { + name: "Immunity", + description: "The immune system of the Pokémon prevents it from getting poisoned.", + }, + flashFire: { + name: "Flash Fire", + description: "Powers up the Pokémon's Fire-type moves if it's hit by one.", + }, + shieldDust: { + name: "Shield Dust", + description: "This Pokémon's dust blocks the additional effects of attacks taken.", + }, + ownTempo: { + name: "Own Tempo", + description: "This Pokémon has its own tempo, and that prevents it from becoming confused.", + }, + suctionCups: { + name: "Suction Cups", + description: "This Pokémon uses suction cups to stay in one spot to negate all moves and items that force switching out.", + }, + intimidate: { + name: "Intimidate", + description: "The Pokémon intimidates opposing Pokémon upon entering battle, lowering their Attack stat.", + }, + shadowTag: { + name: "Shadow Tag", + description: "This Pokémon steps on the opposing Pokémon's shadow to prevent it from escaping.", + }, + roughSkin: { + name: "Rough Skin", + description: "This Pokémon inflicts damage with its rough skin to the attacker on contact.", + }, + wonderGuard: { + name: "Wonder Guard", + description: "Its mysterious power only lets supereffective moves hit the Pokémon.", + }, + levitate: { + name: "Levitate", + description: "By floating in the air, the Pokémon receives full immunity to all Ground-type moves.", + }, + effectSpore: { + name: "Effect Spore", + description: "Contact with the Pokémon may inflict poison, sleep, or paralysis on its attacker.", + }, + synchronize: { + name: "Synchronize", + description: "The attacker will receive the same status condition if it inflicts a burn, poison, or paralysis to the Pokémon.", + }, + clearBody: { + name: "Clear Body", + description: "Prevents other Pokémon's moves or Abilities from lowering the Pokémon's stats.", + }, + naturalCure: { + name: "Natural Cure", + description: "All status conditions heal when the Pokémon switches out.", + }, + lightningRod: { + name: "Lightning Rod", + description: "The Pokémon draws in all Electric-type moves. Instead of being hit by Electric-type moves, it boosts its Sp. Atk.", + }, + sereneGrace: { + name: "Serene Grace", + description: "Boosts the likelihood of additional effects occurring when attacking.", + }, + swiftSwim: { + name: "Swift Swim", + description: "Boosts the Pokémon's Speed stat in rain.", + }, + chlorophyll: { + name: "Chlorophyll", + description: "Boosts the Pokémon's Speed stat in harsh sunlight.", + }, + illuminate: { + name: "Illuminate", + description: "By illuminating its surroundings, the Pokémon raises the likelihood of meeting wild Pokémon and prevents its accuracy from being lowered.", + }, + trace: { + name: "Trace", + description: "When it enters a battle, the Pokémon copies an opposing Pokémon's Ability.", + }, + hugePower: { + name: "Huge Power", + description: "Doubles the Pokémon's Attack stat.", + }, + poisonPoint: { + name: "Poison Point", + description: "Contact with the Pokémon may poison the attacker.", + }, + innerFocus: { + name: "Inner Focus", + description: "The Pokémon's intensely focused, and that protects the Pokémon from flinching.", + }, + magmaArmor: { + name: "Magma Armor", + description: "The Pokémon is covered with hot magma, which prevents the Pokémon from becoming frozen.", + }, + waterVeil: { + name: "Water Veil", + description: "The Pokémon is covered with a water veil, which prevents the Pokémon from getting a burn.", + }, + magnetPull: { + name: "Magnet Pull", + description: "Prevents Steel-type Pokémon from escaping using its magnetic force.", + }, + soundproof: { + name: "Soundproof", + description: "Soundproofing gives the Pokémon full immunity to all sound-based moves.", + }, + rainDish: { + name: "Rain Dish", + description: "The Pokémon gradually regains HP in rain.", + }, + sandStream: { + name: "Sand Stream", + description: "The Pokémon summons a sandstorm when it enters a battle.", + }, + pressure: { + name: "Pressure", + description: "By putting pressure on the opposing Pokémon, it raises their PP usage.", + }, + thickFat: { + name: "Thick Fat", + description: "The Pokémon is protected by a layer of thick fat, which halves the damage taken from Fire- and Ice-type moves.", + }, + earlyBird: { + name: "Early Bird", + description: "The Pokémon awakens from sleep twice as fast as other Pokémon.", + }, + flameBody: { + name: "Flame Body", + description: "Contact with the Pokémon may burn the attacker.", + }, + runAway: { + name: "Run Away", + description: "Enables a sure getaway from wild Pokémon.", + }, + keenEye: { + name: "Keen Eye", + description: "Keen eyes prevent other Pokémon from lowering this Pokémon's accuracy.", + }, + hyperCutter: { + name: "Hyper Cutter", + description: "The Pokémon's proud of its powerful pincers. They prevent other Pokémon from lowering its Attack stat.", + }, + pickup: { + name: "Pickup", + description: "The Pokémon may pick up the item an opposing Pokémon held during a battle.", + }, + truant: { + name: "Truant", + description: "The Pokémon can't use a move if it had used a move on the previous turn.", + }, + hustle: { + name: "Hustle", + description: "Boosts the Attack stat, but lowers accuracy.", + }, + cuteCharm: { + name: "Cute Charm", + description: "Contact with the Pokémon may cause infatuation.", + }, + plus: { + name: "Plus", + description: "Boosts the Sp. Atk stat of the Pokémon if an ally with the Plus or Minus Ability is also in battle.", + }, + minus: { + name: "Minus", + description: "Boosts the Sp. Atk stat of the Pokémon if an ally with the Plus or Minus Ability is also in battle.", + }, + forecast: { + name: "Forecast", + description: "The Pokémon transforms with the weather to change its type to Water, Fire, or Ice.", + }, + stickyHold: { + name: "Sticky Hold", + description: "Items held by the Pokémon are stuck fast and cannot be removed by other Pokémon.", + }, + shedSkin: { + name: "Shed Skin", + description: "The Pokémon may heal its own status conditions by shedding its skin.", + }, + guts: { + name: "Guts", + description: "It's so gutsy that having a status condition boosts the Pokémon's Attack stat.", + }, + marvelScale: { + name: "Marvel Scale", + description: "The Pokémon's marvelous scales boost the Defense stat if it has a status condition.", + }, + liquidOoze: { + name: "Liquid Ooze", + description: "The oozed liquid has a strong stench, which damages attackers using any draining move.", + }, + overgrow: { + name: "Overgrow", + description: "Powers up Grass-type moves when the Pokémon's HP is low.", + }, + blaze: { + name: "Blaze", + description: "Powers up Fire-type moves when the Pokémon's HP is low.", + }, + torrent: { + name: "Torrent", + description: "Powers up Water-type moves when the Pokémon's HP is low.", + }, + swarm: { + name: "Swarm", + description: "Powers up Bug-type moves when the Pokémon's HP is low.", + }, + rockHead: { + name: "Rock Head", + description: "Protects the Pokémon from recoil damage.", + }, + drought: { + name: "Drought", + description: "Turns the sunlight harsh when the Pokémon enters a battle.", + }, + arenaTrap: { + name: "Arena Trap", + description: "Prevents opposing Pokémon from fleeing.", + }, + vitalSpirit: { + name: "Vital Spirit", + description: "The Pokémon is full of vitality, and that prevents it from falling asleep.", + }, + whiteSmoke: { + name: "White Smoke", + description: "The Pokémon is protected by its white smoke, which prevents other Pokémon from lowering its stats.", + }, + purePower: { + name: "Pure Power", + description: "Using its pure power, the Pokémon doubles its Attack stat.", + }, + shellArmor: { + name: "Shell Armor", + description: "A hard shell protects the Pokémon from critical hits.", + }, + airLock: { + name: "Air Lock", + description: "Eliminates the effects of weather.", + }, + tangledFeet: { + name: "Tangled Feet", + description: "Raises evasiveness if the Pokémon is confused.", + }, + motorDrive: { + name: "Motor Drive", + description: "Boosts its Speed stat if hit by an Electric-type move instead of taking damage.", + }, + rivalry: { + name: "Rivalry", + description: "Becomes competitive and deals more damage to Pokémon of the same gender, but deals less to Pokémon of the opposite gender.", + }, + steadfast: { + name: "Steadfast", + description: "The Pokémon's determination boosts the Speed stat each time the Pokémon flinches.", + }, + snowCloak: { + name: "Snow Cloak", + description: "Boosts the Pokémon's evasiveness in snow.", + }, + gluttony: { + name: "Gluttony", + description: "Makes the Pokémon eat a held Berry when its HP drops to half or less, which is sooner than usual.", + }, + angerPoint: { + name: "Anger Point", + description: "The Pokémon is angered when it takes a critical hit, and that maxes its Attack stat.", + }, + unburden: { + name: "Unburden", + description: "Boosts the Speed stat if the Pokémon's held item is used or lost.", + }, + heatproof: { + name: "Heatproof", + description: "The heatproof body of the Pokémon halves the damage from Fire-type moves that hit it.", + }, + simple: { + name: "Simple", + description: "The stat changes the Pokémon receives are doubled.", + }, + drySkin: { + name: "Dry Skin", + description: "Restores HP in rain or when hit by Water-type moves. Reduces HP in harsh sunlight, and increases the damage received from Fire-type moves.", + }, + download: { + name: "Download", + description: "Compares an opposing Pokémon's Defense and Sp. Def stats before raising its own Attack or Sp. Atk stat—whichever will be more effective.", + }, + ironFist: { + name: "Iron Fist", + description: "Powers up punching moves.", + }, + poisonHeal: { + name: "Poison Heal", + description: "Restores HP if the Pokémon is poisoned instead of losing HP.", + }, + adaptability: { + name: "Adaptability", + description: "Powers up moves of the same type as the Pokémon.", + }, + skillLink: { + name: "Skill Link", + description: "Maximizes the number of times multistrike moves hit.", + }, + hydration: { + name: "Hydration", + description: "Heals status conditions if it's raining.", + }, + solarPower: { + name: "Solar Power", + description: "Boosts the Sp. Atk stat in harsh sunlight, but HP decreases every turn.", + }, + quickFeet: { + name: "Quick Feet", + description: "Boosts the Speed stat if the Pokémon has a status condition.", + }, + normalize: { + name: "Normalize", + description: "All the Pokémon's moves become Normal type. The power of those moves is boosted a little.", + }, + sniper: { + name: "Sniper", + description: "Powers up moves if they become critical hits when attacking.", + }, + magicGuard: { + name: "Magic Guard", + description: "The Pokémon only takes damage from attacks.", + }, + noGuard: { + name: "No Guard", + description: "The Pokémon employs no-guard tactics to ensure incoming and outgoing attacks always land.", + }, + stall: { + name: "Stall", + description: "The Pokémon moves after all other Pokémon do.", + }, + technician: { + name: "Technician", + description: "Powers up the Pokémon's weaker moves.", + }, + leafGuard: { + name: "Leaf Guard", + description: "Prevents status conditions in harsh sunlight.", + }, + klutz: { + name: "Klutz", + description: "The Pokémon can't use any held items.", + }, + moldBreaker: { + name: "Mold Breaker", + description: "Moves can be used on the target regardless of its Abilities.", + }, + superLuck: { + name: "Super Luck", + description: "The Pokémon is so lucky that the critical-hit ratios of its moves are boosted.", + }, + aftermath: { + name: "Aftermath", + description: "Damages the attacker if it contacts the Pokémon with a finishing hit.", + }, + anticipation: { + name: "Anticipation", + description: "The Pokémon can sense an opposing Pokémon's dangerous moves.", + }, + forewarn: { + name: "Forewarn", + description: "When it enters a battle, the Pokémon can tell one of the moves an opposing Pokémon has.", + }, + unaware: { + name: "Unaware", + description: "When attacking, the Pokémon ignores the target Pokémon's stat changes.", + }, + tintedLens: { + name: "Tinted Lens", + description: 'The Pokémon can use "not very effective" moves to deal regular damage.', + }, + filter: { + name: "Filter", + description: "Reduces the power of supereffective attacks taken.", + }, + slowStart: { + name: "Slow Start", + description: "For five turns, the Pokémon's Attack and Speed stats are halved.", + }, + scrappy: { + name: "Scrappy", + description: "The Pokémon can hit Ghost-type Pokémon with Normal- and Fighting-type moves.", + }, + stormDrain: { + name: "Storm Drain", + description: "Draws in all Water-type moves. Instead of being hit by Water-type moves, it boosts its Sp. Atk.", + }, + iceBody: { + name: "Ice Body", + description: "The Pokémon gradually regains HP in snow.", + }, + solidRock: { + name: "Solid Rock", + description: "Reduces the power of supereffective attacks taken.", + }, + snowWarning: { + name: "Snow Warning", + description: "The Pokémon makes it snow when it enters a battle.", + }, + honeyGather: { + name: "Honey Gather", + description: "The Pokémon may gather Honey after a battle.", + }, + frisk: { + name: "Frisk", + description: "When it enters a battle, the Pokémon can check an opposing Pokémon's held item.", + }, + reckless: { + name: "Reckless", + description: "Powers up moves that have recoil damage.", + }, + multitype: { + name: "Multitype", + description: "Changes the Pokémon's type to match the Plate or Z-Crystal it holds.", + }, + flowerGift: { + name: "Flower Gift", + description: "Boosts the Attack and Sp. Def stats of itself and allies in harsh sunlight.", + }, + badDreams: { + name: "Bad Dreams", + description: "Reduces the HP of sleeping opposing Pokémon.", + }, + pickpocket: { + name: "Pickpocket", + description: "Steals an item from an attacker that made direct contact.", + }, + sheerForce: { + name: "Sheer Force", + description: "Removes additional effects to increase the power of moves when attacking.", + }, + contrary: { + name: "Contrary", + description: "Makes stat changes have an opposite effect.", + }, + unnerve: { + name: "Unnerve", + description: "Unnerves opposing Pokémon and makes them unable to eat Berries.", + }, + defiant: { + name: "Defiant", + description: "Boosts the Pokémon's Attack stat sharply when its stats are lowered.", + }, + defeatist: { + name: "Defeatist", + description: "Halves the Pokémon's Attack and Sp. Atk stats when its HP becomes half or less.", + }, + cursedBody: { + name: "Cursed Body", + description: "May disable a move used on the Pokémon.", + }, + healer: { + name: "Healer", + description: "Sometimes heals an ally's status condition.", + }, + friendGuard: { + name: "Friend Guard", + description: "Reduces damage done to allies.", + }, + weakArmor: { + name: "Weak Armor", + description: "Physical attacks to the Pokémon lower its Defense stat but sharply raise its Speed stat.", + }, + heavyMetal: { + name: "Heavy Metal", + description: "Doubles the Pokémon's weight.", + }, + lightMetal: { + name: "Light Metal", + description: "Halves the Pokémon's weight.", + }, + multiscale: { + name: "Multiscale", + description: "Reduces the amount of damage the Pokémon takes while its HP is full.", + }, + toxicBoost: { + name: "Toxic Boost", + description: "Powers up physical attacks when the Pokémon is poisoned.", + }, + flareBoost: { + name: "Flare Boost", + description: "Powers up special attacks when the Pokémon is burned.", + }, + harvest: { + name: "Harvest", + description: "May create another Berry after one is used.", + }, + telepathy: { + name: "Telepathy", + description: "Anticipates an ally's attack and dodges it.", + }, + moody: { + name: "Moody", + description: "Raises one stat sharply and lowers another every turn.", + }, + overcoat: { + name: "Overcoat", + description: "Protects the Pokémon from things like sand, hail, and powder.", + }, + poisonTouch: { + name: "Poison Touch", + description: "May poison a target when the Pokémon makes contact.", + }, + regenerator: { + name: "Regenerator", + description: "Restores a little HP when withdrawn from battle.", + }, + bigPecks: { + name: "Big Pecks", + description: "Protects the Pokémon from Defense-lowering effects.", + }, + sandRush: { + name: "Sand Rush", + description: "Boosts the Pokémon's Speed stat in a sandstorm.", + }, + wonderSkin: { + name: "Wonder Skin", + description: "Makes status moves more likely to miss.", + }, + analytic: { + name: "Analytic", + description: "Boosts move power when the Pokémon moves last.", + }, + illusion: { + name: "Illusion", + description: "Comes out disguised as the Pokémon in the party's last spot.", + }, + imposter: { + name: "Imposter", + description: "The Pokémon transforms itself into the Pokémon it's facing.", + }, + infiltrator: { + name: "Infiltrator", + description: "Passes through the opposing Pokémon's barrier, substitute, and the like and strikes.", + }, + mummy: { + name: "Mummy", + description: "Contact with the Pokémon changes the attacker's Ability to Mummy.", + }, + moxie: { + name: "Moxie", + description: "The Pokémon shows moxie, and that boosts the Attack stat after knocking out any Pokémon.", + }, + justified: { + name: "Justified", + description: "Being hit by a Dark-type move boosts the Attack stat of the Pokémon, for justice.", + }, + rattled: { + name: "Rattled", + description: "Intimidate or being hit by a Dark-, Ghost-, or Bug-type move will scare the Pokémon and boost its Speed stat.", + }, + magicBounce: { + name: "Magic Bounce", + description: "Reflects status moves instead of getting hit by them.", + }, + sapSipper: { + name: "Sap Sipper", + description: "Boosts the Attack stat if hit by a Grass-type move instead of taking damage.", + }, + prankster: { + name: "Prankster", + description: "Gives priority to a status move.", + }, + sandForce: { + name: "Sand Force", + description: "Boosts the power of Rock-, Ground-, and Steel-type moves in a sandstorm.", + }, + ironBarbs: { + name: "Iron Barbs", + description: "Inflicts damage on the attacker upon contact with iron barbs.", + }, + zenMode: { + name: "Zen Mode", + description: "Changes the Pokémon's shape when HP is half or less.", + }, + victoryStar: { + name: "Victory Star", + description: "Boosts the accuracy of its allies and itself.", + }, + turboblaze: { + name: "Turboblaze", + description: "Moves can be used on the target regardless of its Abilities.", + }, + teravolt: { + name: "Teravolt", + description: "Moves can be used on the target regardless of its Abilities.", + }, + aromaVeil: { + name: "Aroma Veil", + description: "Protects itself and its allies from attacks that limit their move choices.", + }, + flowerVeil: { + name: "Flower Veil", + description: "Ally Grass-type Pokémon are protected from status conditions and the lowering of their stats.", + }, + cheekPouch: { + name: "Cheek Pouch", + description: "Restores HP as well when the Pokémon eats a Berry.", + }, + protean: { + name: "Protean", + description: "Changes the Pokémon's type to the type of the move it's about to use.", + }, + furCoat: { + name: "Fur Coat", + description: "Halves the damage from physical moves.", + }, + magician: { + name: "Magician", + description: "The Pokémon steals the held item of a Pokémon it hits with a move.", + }, + bulletproof: { + name: "Bulletproof", + description: "Protects the Pokémon from some ball and bomb moves.", + }, + competitive: { + name: "Competitive", + description: "Boosts the Sp. Atk stat sharply when a stat is lowered.", + }, + strongJaw: { + name: "Strong Jaw", + description: "The Pokémon's strong jaw boosts the power of its biting moves.", + }, + refrigerate: { + name: "Refrigerate", + description: "Normal-type moves become Ice-type moves. The power of those moves is boosted a little.", + }, + sweetVeil: { + name: "Sweet Veil", + description: "Prevents itself and ally Pokémon from falling asleep.", + }, + stanceChange: { + name: "Stance Change", + description: "The Pokémon changes its form to Blade Forme when it uses an attack move and changes to Shield Forme when it uses King's Shield.", + }, + galeWings: { + name: "Gale Wings", + description: "Gives priority to Flying-type moves when the Pokémon's HP is full.", + }, + megaLauncher: { + name: "Mega Launcher", + description: "Powers up aura and pulse moves.", + }, + grassPelt: { + name: "Grass Pelt", + description: "Boosts the Pokémon's Defense stat on Grassy Terrain.", + }, + symbiosis: { + name: "Symbiosis", + description: "The Pokémon passes its item to an ally that has used up an item.", + }, + toughClaws: { + name: "Tough Claws", + description: "Powers up moves that make direct contact.", + }, + pixilate: { + name: "Pixilate", + description: "Normal-type moves become Fairy-type moves. The power of those moves is boosted a little.", + }, + gooey: { + name: "Gooey", + description: "Contact with the Pokémon lowers the attacker's Speed stat.", + }, + aerilate: { + name: "Aerilate", + description: "Normal-type moves become Flying-type moves. The power of those moves is boosted a little.", + }, + parentalBond: { + name: "Parental Bond", + description: "Parent and child each attacks.", + }, + darkAura: { + name: "Dark Aura", + description: "Powers up each Pokémon's Dark-type moves.", + }, + fairyAura: { + name: "Fairy Aura", + description: "Powers up each Pokémon's Fairy-type moves.", + }, + auraBreak: { + name: "Aura Break", + description: 'The effects of "Aura" Abilities are reversed to lower the power of affected moves.', + }, + primordialSea: { + name: "Primordial Sea", + description: "The Pokémon changes the weather to nullify Fire-type attacks.", + }, + desolateLand: { + name: "Desolate Land", + description: "The Pokémon changes the weather to nullify Water-type attacks.", + }, + deltaStream: { + name: "Delta Stream", + description: "The Pokémon changes the weather to eliminate all of the Flying type's weaknesses.", + }, + stamina: { + name: "Stamina", + description: "Boosts the Defense stat when hit by an attack.", + }, + wimpOut: { + name: "Wimp Out", + description: "The Pokémon cowardly switches out when its HP becomes half or less.", + }, + emergencyExit: { + name: "Emergency Exit", + description: "The Pokémon, sensing danger, switches out when its HP becomes half or less.", + }, + waterCompaction: { + name: "Water Compaction", + description: "Boosts the Pokémon's Defense stat sharply when hit by a Water-type move.", + }, + merciless: { + name: "Merciless", + description: "The Pokémon's attacks become critical hits if the target is poisoned.", + }, + shieldsDown: { + name: "Shields Down", + description: "When its HP becomes half or less, the Pokémon's shell breaks and it becomes aggressive.", + }, + stakeout: { + name: "Stakeout", + description: "Doubles the damage dealt to the target's replacement if the target switches out.", + }, + waterBubble: { + name: "Water Bubble", + description: "Lowers the power of Fire-type moves done to the Pokémon and prevents the Pokémon from getting a burn.", + }, + steelworker: { + name: "Steelworker", + description: "Powers up Steel-type moves.", + }, + berserk: { + name: "Berserk", + description: "Boosts the Pokémon's Sp. Atk stat when it takes a hit that causes its HP to become half or less.", + }, + slushRush: { + name: "Slush Rush", + description: "Boosts the Pokémon's Speed stat in snow.", + }, + longReach: { + name: "Long Reach", + description: "The Pokémon uses its moves without making contact with the target.", + }, + liquidVoice: { + name: "Liquid Voice", + description: "All sound-based moves become Water-type moves.", + }, + triage: { + name: "Triage", + description: "Gives priority to a healing move.", + }, + galvanize: { + name: "Galvanize", + description: "Normal-type moves become Electric-type moves. The power of those moves is boosted a little.", + }, + surgeSurfer: { + name: "Surge Surfer", + description: "Doubles the Pokémon's Speed stat on Electric Terrain.", + }, + schooling: { + name: "Schooling", + description: "When it has a lot of HP, the Pokémon forms a powerful school. It stops schooling when its HP is low.", + }, + disguise: { + name: "Disguise", + description: "Once per battle, the shroud that covers the Pokémon can protect it from an attack.", + }, + battleBond: { + name: "Battle Bond", + description: "Defeating an opposing Pokémon strengthens the Pokémon's bond with its Trainer, and it becomes Ash-Greninja. Water Shuriken gets more powerful.", + }, + powerConstruct: { + name: "Power Construct", + description: "Other Cells gather to aid when its HP becomes half or less. Then the Pokémon changes its form to Complete Forme.", + }, + corrosion: { + name: "Corrosion", + description: "The Pokémon can poison the target even if it's a Steel or Poison type.", + }, + comatose: { + name: "Comatose", + description: "It's always drowsing and will never wake up. It can attack without waking up.", + }, + queenlyMajesty: { + name: "Queenly Majesty", + description: "Its majesty pressures the opposing Pokémon, making it unable to attack using priority moves.", + }, + innardsOut: { + name: "Innards Out", + description: "Damages the attacker landing the finishing hit by the amount equal to its last HP.", + }, + dancer: { + name: "Dancer", + description: "When another Pokémon uses a dance move, it can use a dance move following it regardless of its Speed.", + }, + battery: { + name: "Battery", + description: "Powers up ally Pokémon's special moves.", + }, + fluffy: { + name: "Fluffy", + description: "Halves the damage taken from moves that make direct contact, but doubles that of Fire-type moves.", + }, + dazzling: { + name: "Dazzling", + description: "Surprises the opposing Pokémon, making it unable to attack using priority moves.", + }, + soulHeart: { + name: "Soul-Heart", + description: "Boosts its Sp. Atk stat every time a Pokémon faints.", + }, + tanglingHair: { + name: "Tangling Hair", + description: "Contact with the Pokémon lowers the attacker's Speed stat.", + }, + receiver: { + name: "Receiver", + description: "The Pokémon copies the Ability of a defeated ally.", + }, + powerOfAlchemy: { + name: "Power of Alchemy", + description: "The Pokémon copies the Ability of a defeated ally.", + }, + beastBoost: { + name: "Beast Boost", + description: "The Pokémon boosts its most proficient stat each time it knocks out a Pokémon.", + }, + rksSystem: { + name: "RKS System", + description: "Changes the Pokémon's type to match the memory disc it holds.", + }, + electricSurge: { + name: "Electric Surge", + description: "Turns the ground into Electric Terrain when the Pokémon enters a battle.", + }, + psychicSurge: { + name: "Psychic Surge", + description: "Turns the ground into Psychic Terrain when the Pokémon enters a battle.", + }, + mistySurge: { + name: "Misty Surge", + description: "Turns the ground into Misty Terrain when the Pokémon enters a battle.", + }, + grassySurge: { + name: "Grassy Surge", + description: "Turns the ground into Grassy Terrain when the Pokémon enters a battle.", + }, + fullMetalBody: { + name: "Full Metal Body", + description: "Prevents other Pokémon's moves or Abilities from lowering the Pokémon's stats.", + }, + shadowShield: { + name: "Shadow Shield", + description: "Reduces the amount of damage the Pokémon takes while its HP is full.", + }, + prismArmor: { + name: "Prism Armor", + description: "Reduces the power of supereffective attacks taken.", + }, + neuroforce: { + name: "Neuroforce", + description: "Powers up moves that are super effective.", + }, + intrepidSword: { + name: "Intrepid Sword", + description: "Boosts the Pokémon's Attack stat when the Pokémon enters a battle.", + }, + dauntlessShield: { + name: "Dauntless Shield", + description: "Boosts the Pokémon's Defense stat when the Pokémon enters a battle.", + }, + libero: { + name: "Libero", + description: "Changes the Pokémon's type to the type of the move it's about to use.", + }, + ballFetch: { + name: "Ball Fetch", + description: "The Pokémon will fetch the Poké Ball from the first failed throw of the battle.", + }, + cottonDown: { + name: "Cotton Down", + description: "When the Pokémon is hit by an attack, it scatters cotton fluff around and lowers the Speed stat of all Pokémon except itself.", + }, + propellerTail: { + name: "Propeller Tail", + description: "Ignores the effects of opposing Pokémon's Abilities and moves that draw in moves.", + }, + mirrorArmor: { + name: "Mirror Armor", + description: "Bounces back only the stat-lowering effects that the Pokémon receives.", + }, + gulpMissile: { + name: "Gulp Missile", + description: "When the Pokémon uses Surf or Dive, it will come back with prey. When it takes damage, it will spit out the prey to attack.", + }, + stalwart: { + name: "Stalwart", + description: "Ignores the effects of opposing Pokémon's Abilities and moves that draw in moves.", + }, + steamEngine: { + name: "Steam Engine", + description: "Boosts the Pokémon's Speed stat drastically if hit by a Fire- or Water-type move.", + }, + punkRock: { + name: "Punk Rock", + description: "Boosts the power of sound-based moves. The Pokémon also takes half the damage from these kinds of moves.", + }, + sandSpit: { + name: "Sand Spit", + description: "The Pokémon creates a sandstorm when it's hit by an attack.", + }, + iceScales: { + name: "Ice Scales", + description: "The Pokémon is protected by ice scales, which halve the damage taken from special moves.", + }, + ripen: { + name: "Ripen", + description: "Ripens Berries and doubles their effect.", + }, + iceFace: { + name: "Ice Face", + description: "The Pokémon's ice head can take a physical attack as a substitute, but the attack also changes the Pokémon's appearance. The ice will be restored when it hails.", + }, + powerSpot: { + name: "Power Spot", + description: "Just being next to the Pokémon powers up moves.", + }, + mimicry: { + name: "Mimicry", + description: "Changes the Pokémon's type depending on the terrain.", + }, + screenCleaner: { + name: "Screen Cleaner", + description: "When the Pokémon enters a battle, the effects of Light Screen, Reflect, and Aurora Veil are nullified for both opposing and ally Pokémon.", + }, + steelySpirit: { + name: "Steely Spirit", + description: "Powers up ally Pokémon's Steel-type moves.", + }, + perishBody: { + name: "Perish Body", + description: "When hit by a move that makes direct contact, the Pokémon and the attacker will faint after three turns unless they switch out of battle.", + }, + wanderingSpirit: { + name: "Wandering Spirit", + description: "The Pokémon exchanges Abilities with a Pokémon that hits it with a move that makes direct contact.", + }, + gorillaTactics: { + name: "Gorilla Tactics", + description: "Boosts the Pokémon's Attack stat but only allows the use of the first selected move.", + }, + neutralizingGas: { + name: "Neutralizing Gas", + description: "If the Pokémon with Neutralizing Gas is in the battle, the effects of all Pokémon's Abilities will be nullified or will not be triggered.", + }, + pastelVeil: { + name: "Pastel Veil", + description: "Protects the Pokémon and its ally Pokémon from being poisoned.", + }, + hungerSwitch: { + name: "Hunger Switch", + description: "The Pokémon changes its form, alternating between its Full Belly Mode and Hangry Mode after the end of each turn.", + }, + quickDraw: { + name: "Quick Draw", + description: "Enables the Pokémon to move first occasionally.", + }, + unseenFist: { + name: "Unseen Fist", + description: "If the Pokémon uses moves that make direct contact, it can attack the target even if the target protects itself.", + }, + curiousMedicine: { + name: "Curious Medicine", + description: "When the Pokémon enters a battle, it scatters medicine from its shell, which removes all stat changes from allies.", + }, + transistor: { + name: "Transistor", + description: "Powers up Electric-type moves.", + }, + dragonsMaw: { + name: "Dragon's Maw", + description: "Powers up Dragon-type moves.", + }, + chillingNeigh: { + name: "Chilling Neigh", + description: "When the Pokémon knocks out a target, it utters a chilling neigh, which boosts its Attack stat.", + }, + grimNeigh: { + name: "Grim Neigh", + description: "When the Pokémon knocks out a target, it utters a terrifying neigh, which boosts its Sp. Atk stat.", + }, + asOneGlastrier: { + name: "As One", + description: "This Ability combines the effects of both Calyrex's Unnerve Ability and Glastrier's Chilling Neigh Ability.", + }, + asOneSpectrier: { + name: "As One", + description: "This Ability combines the effects of both Calyrex's Unnerve Ability and Spectrier's Grim Neigh Ability.", + }, + lingeringAroma: { + name: "Lingering Aroma", + description: "Contact with the Pokémon changes the attacker's Ability to Lingering Aroma.", + }, + seedSower: { + name: "Seed Sower", + description: "Turns the ground into Grassy Terrain when the Pokémon is hit by an attack.", + }, + thermalExchange: { + name: "Thermal Exchange", + description: "Boosts the Attack stat when the Pokémon is hit by a Fire-type move. The Pokémon also cannot be burned.", + }, + angerShell: { + name: "Anger Shell", + description: "When an attack causes its HP to drop to half or less, the Pokémon gets angry. This lowers its Defense and Sp. Def stats but boosts its Attack, Sp. Atk, and Speed stats.", + }, + purifyingSalt: { + name: "Purifying Salt", + description: "The Pokémon's pure salt protects it from status conditions and halves the damage taken from Ghost-type moves.", + }, + wellBakedBody: { + name: "Well-Baked Body", + description: "The Pokémon takes no damage when hit by Fire-type moves. Instead, its Defense stat is sharply boosted.", + }, + windRider: { + name: "Wind Rider", + description: "Boosts the Pokémon's Attack stat if Tailwind takes effect or if the Pokémon is hit by a wind move. The Pokémon also takes no damage from wind moves.", + }, + guardDog: { + name: "Guard Dog", + description: "Boosts the Pokémon's Attack stat if intimidated. Moves and items that would force the Pokémon to switch out also fail to work.", + }, + rockyPayload: { + name: "Rocky Payload", + description: "Powers up Rock-type moves.", + }, + windPower: { + name: "Wind Power", + description: "The Pokémon becomes charged when it is hit by a wind move, boosting the power of the next Electric-type move the Pokémon uses.", + }, + zeroToHero: { + name: "Zero to Hero", + description: "The Pokémon transforms into its Hero Form when it switches out.", + }, + commander: { + name: "Commander", + description: "When the Pokémon enters a battle, it goes inside the mouth of an ally Dondozo if one is on the field. The Pokémon then issues commands from there.", + }, + electromorphosis: { + name: "Electromorphosis", + description: "The Pokémon becomes charged when it takes damage, boosting the power of the next Electric-type move the Pokémon uses.", + }, + protosynthesis: { + name: "Protosynthesis", + description: "Boosts the Pokémon's most proficient stat in harsh sunlight or if the Pokémon is holding Booster Energy.", + }, + quarkDrive: { + name: "Quark Drive", + description: "Boosts the Pokémon's most proficient stat on Electric Terrain or if the Pokémon is holding Booster Energy.", + }, + goodAsGold: { + name: "Good as Gold", + description: "A body of pure, solid gold gives the Pokémon full immunity to other Pokémon's status moves.", + }, + vesselOfRuin: { + name: "Vessel of Ruin", + description: "The power of the Pokémon's ruinous vessel lowers the Sp. Atk stats of all Pokémon except itself.", + }, + swordOfRuin: { + name: "Sword of Ruin", + description: "The power of the Pokémon's ruinous sword lowers the Defense stats of all Pokémon except itself.", + }, + tabletsOfRuin: { + name: "Tablets of Ruin", + description: "The power of the Pokémon's ruinous wooden tablets lowers the Attack stats of all Pokémon except itself.", + }, + beadsOfRuin: { + name: "Beads of Ruin", + description: "The power of the Pokémon's ruinous beads lowers the Sp. Def stats of all Pokémon except itself.", + }, + orichalcumPulse: { + name: "Orichalcum Pulse", + description: "Turns the sunlight harsh when the Pokémon enters a battle. The ancient pulse thrumming through the Pokémon also boosts its Attack stat in harsh sunlight.", + }, + hadronEngine: { + name: "Hadron Engine", + description: "Turns the ground into Electric Terrain when the Pokémon enters a battle. The futuristic engine within the Pokémon also boosts its Sp. Atk stat on Electric Terrain.", + }, + opportunist: { + name: "Opportunist", + description: "If an opponent's stat is boosted, the Pokémon seizes the opportunity to boost the same stat for itself.", + }, + cudChew: { + name: "Cud Chew", + description: "When the Pokémon eats a Berry, it will regurgitate that Berry at the end of the next turn and eat it one more time.", + }, + sharpness: { + name: "Sharpness", + description: "Powers up slicing moves.", + }, + supremeOverlord: { + name: "Supreme Overlord", + description: "When the Pokémon enters a battle, its Attack and Sp. Atk stats are slightly boosted for each of the allies in its party that have already been defeated.", + }, + costar: { + name: "Costar", + description: "When the Pokémon enters a battle, it copies an ally's stat changes.", + }, + toxicDebris: { + name: "Toxic Debris", + description: "Scatters poison spikes at the feet of the opposing team when the Pokémon takes damage from physical moves.", + }, + armorTail: { + name: "Armor Tail", + description: "The mysterious tail covering the Pokémon's head makes opponents unable to use priority moves against the Pokémon or its allies.", + }, + earthEater: { + name: "Earth Eater", + description: "If hit by a Ground-type move, the Pokémon has its HP restored instead of taking damage.", + }, + myceliumMight: { + name: "Mycelium Might", + description: "The Pokémon will always act more slowly when using status moves, but these moves will be unimpeded by the Ability of the target.", + }, + mindsEye: { + name: "Mind's Eye", + description: "The Pokémon ignores changes to opponents' evasiveness, its accuracy can't be lowered, and it can hit Ghost types with Normal- and Fighting-type moves.", + }, + supersweetSyrup: { + name: "Supersweet Syrup", + description: "A sickly sweet scent spreads across the field the first time the Pokémon enters a battle, lowering the evasiveness of opposing Pokémon.", + }, + hospitality: { + name: "Hospitality", + description: "When the Pokémon enters a battle, it showers its ally with hospitality, restoring a small amount of the ally's HP.", + }, + toxicChain: { + name: "Toxic Chain", + description: "The power of the Pokémon's toxic chain may badly poison any target the Pokémon hits with a move.", + }, + embodyAspectTeal: { + name: "Embody Aspect", + description: "The Pokémon's heart fills with memories, causing the Teal Mask to shine and the Pokémon's Speed stat to be boosted.", + }, + embodyAspectWellspring: { + name: "Embody Aspect", + description: "The Pokémon's heart fills with memories, causing the Wellspring Mask to shine and the Pokémon's Sp. Def stat to be boosted.", + }, + embodyAspectHearthflame: { + name: "Embody Aspect", + description: "The Pokémon's heart fills with memories, causing the Hearthflame Mask to shine and the Pokémon's Attack stat to be boosted.", + }, + embodyAspectCornerstone: { + name: "Embody Aspect", + description: "The Pokémon's heart fills with memories, causing the Cornerstone Mask to shine and the Pokémon's Defense stat to be boosted.", + }, + teraShift: { + name: "Tera Shift", + description: "When the Pokémon enters a battle, it absorbs the energy around itself and transforms into its Terastal Form.", + }, + teraShell: { + name: "Tera Shell", + description: "The Pokémon's shell contains the powers of each type. All damage-dealing moves that hit the Pokémon when its HP is full will not be very effective.", + }, + teraformZero: { + name: "Teraform Zero", + description: "When Terapagos changes into its Stellar Form, it uses its hidden powers to eliminate all effects of weather and terrain, reducing them to zero.", + }, + poisonPuppeteer: { + name: "Poison Puppeteer", + description: "Pokémon poisoned by Pecharunt's moves will also become confused.", + }, +} as const; diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 31ddc2d6c79..a69f441d895 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -8,6 +8,10 @@ import { move as enMove } from '../locales/en/move'; import { move as esMove } from '../locales/es/move'; import { move as frMove } from '../locales/fr/move'; +import { ability as enAbility } from '../locales/en/ability'; +import { ability as esAbility } from '../locales/es/ability'; +import { ability as frAbility } from '../locales/fr/ability'; + import { pokeball as enPokeball } from '../locales/en/pokeball'; import { pokeball as esPokeball } from '../locales/es/pokeball'; import { pokeball as frPokeball } from '../locales/fr/pokeball'; @@ -39,6 +43,15 @@ export interface MoveTranslationEntries { [key: string]: MoveTranslationEntry } +export interface AbilityTranslationEntry { + name: string, + description: string +} + +export interface AbilityTranslationEntries { + [key: string]: AbilityTranslationEntry +} + export interface Localizable { localize(): void; } @@ -74,6 +87,7 @@ export function initI18n(): void { en: { menu: enMenu, move: enMove, + ability: enAbility, pokeball: enPokeball, pokemon: enPokemon, pokemonStat: enPokemonStat, @@ -82,6 +96,7 @@ export function initI18n(): void { es: { menu: esMenu, move: esMove, + ability: esAbility, pokeball: esPokeball, pokemon: esPokemon, pokemonStat: esPokemonStat, @@ -90,6 +105,7 @@ export function initI18n(): void { fr: { menu: frMenu, move: frMove, + ability: frAbility, pokeball: frPokeball, pokemon: frPokemon, pokemonStat: frPokemonStat, @@ -109,6 +125,7 @@ declare module 'i18next' { resources: { menu: typeof enMenu; move: typeof enMove; + ability: typeof enAbility; pokeball: typeof enPokeball; pokemon: typeof enPokemon; pokemonStat: typeof enPokemonStat; From 269db124363a072a2e510bf09d920464d78c511b Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 24 Apr 2024 21:21:28 -0400 Subject: [PATCH 26/30] Add missing URI component encoding on login --- src/ui/login-form-ui-handler.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/login-form-ui-handler.ts b/src/ui/login-form-ui-handler.ts index 27de954632f..f77efcad260 100644 --- a/src/ui/login-form-ui-handler.ts +++ b/src/ui/login-form-ui-handler.ts @@ -59,7 +59,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler { }; if (!this.inputs[0].text) return onFail(i18next.t('menu:emptyUsername')); - Utils.apiPost(`account/login`, `username=${this.inputs[0].text}&password=${this.inputs[1].text}`, 'application/x-www-form-urlencoded') + Utils.apiPost(`account/login`, `username=${encodeURIComponent(this.inputs[0].text)}&password=${encodeURIComponent(this.inputs[1].text)}`, 'application/x-www-form-urlencoded') .then(response => { if (!response.ok) return response.text(); From a0311f4b0fee45d748f072b9f437ccd789acb85e Mon Sep 17 00:00:00 2001 From: Flashfyre Date: Wed, 24 Apr 2024 22:42:09 -0400 Subject: [PATCH 27/30] Fix partial and unimplemented indicators not showing on abilities --- src/data/ability.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/data/ability.ts b/src/data/ability.ts index 4b8dee38b62..b7acb552920 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -22,6 +22,8 @@ import i18next, { Localizable } from "#app/plugins/i18n.js"; export class Ability implements Localizable { public id: Abilities; + + private nameAppend: string; public name: string; public description: string; public generation: integer; @@ -32,6 +34,8 @@ export class Ability implements Localizable { constructor(id: Abilities, generation: integer) { this.id = id; + + this.nameAppend = ''; this.generation = generation; this.attrs = []; this.conditions = []; @@ -42,7 +46,7 @@ export class Ability implements Localizable { localize(): void { const i18nKey = Abilities[this.id].split('_').filter(f => f).map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join('') as string; - this.name = this.id ? i18next.t(`ability:${i18nKey}.name`) as string : ''; + this.name = this.id ? `${i18next.t(`ability:${i18nKey}.name`) as string}${this.nameAppend}` : ''; this.description = this.id ? i18next.t(`ability:${i18nKey}.description`) as string : ''; } @@ -86,12 +90,12 @@ export class Ability implements Localizable { } partial(): this { - this.name += ' (P)'; + this.nameAppend += ' (P)'; return this; } unimplemented(): this { - this.name += ' (N)'; + this.nameAppend += ' (N)'; return this; } } From ac15c653d6681c428c5d06f9336b9f8178d04125 Mon Sep 17 00:00:00 2001 From: maru Date: Wed, 24 Apr 2024 23:06:42 -0400 Subject: [PATCH 28/30] Add no-times to rsync in deploy job --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index db8fa2777e5..1ae295180f9 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -29,5 +29,5 @@ jobs: - name: Deploy build on server if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch run: | - rsync --del -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }} + rsync --del --no-times -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }} ssh -t ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/prmanifest --inpath ${{ secrets.DESTINATION_DIR }} --outpath ${{ secrets.DESTINATION_DIR }}/manifest.json" From 7ff82440bc93bb3a1bcbeb79315fd93f93060c92 Mon Sep 17 00:00:00 2001 From: maru Date: Wed, 24 Apr 2024 23:10:16 -0400 Subject: [PATCH 29/30] Add checksum to rsync in deploy job --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1ae295180f9..fcf0ec03a0a 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -29,5 +29,5 @@ jobs: - name: Deploy build on server if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch run: | - rsync --del --no-times -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }} + rsync --del --no-times --checksum -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }} ssh -t ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/prmanifest --inpath ${{ secrets.DESTINATION_DIR }} --outpath ${{ secrets.DESTINATION_DIR }}/manifest.json" From 145267c9a66e4cbf909c39862134a1950fda87ac Mon Sep 17 00:00:00 2001 From: John Martin Date: Wed, 24 Apr 2024 23:29:47 -0400 Subject: [PATCH 30/30] Fixed leftover text re-corrections. (#283) * Minor text corrections to item descriptions. * Update modifier-type.ts; minor text correction updates * Update modifier-type.ts; further text re-corrections. * Update modifier-type.ts; leftover re-corrections. * Minor text corrections in modifier menu. --- src/modifier/modifier-type.ts | 4 ++-- src/ui/modifier-select-ui-handler.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 354f80f91fe..76ab3bd5f78 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -213,7 +213,7 @@ export class PokemonReviveModifierType extends PokemonHpRestoreModifierType { return null; }), iconImage, 'revive'); - this.description = `Revive one Pokémon and restore ${restorePercent}% HP.`; + this.description = `Revives one Pokémon and restores ${restorePercent}% HP`; this.selectFilter = (pokemon: PlayerPokemon) => { if (pokemon.hp) return PartyUiHandler.NoEffectMessage; @@ -224,7 +224,7 @@ export class PokemonReviveModifierType extends PokemonHpRestoreModifierType { export class PokemonStatusHealModifierType extends PokemonModifierType { constructor(name: string) { - super(name, `Heal any status ailment for one Pokémon.`, + super(name, `Heals any status ailment for one Pokémon`, ((_type, args) => new Modifiers.PokemonStatusHealModifier(this, (args[0] as PlayerPokemon).id)), ((pokemon: PlayerPokemon) => { if (!pokemon.hp || !pokemon.status) diff --git a/src/ui/modifier-select-ui-handler.ts b/src/ui/modifier-select-ui-handler.ts index 6b4cf30b0df..1bd44bfd3c4 100644 --- a/src/ui/modifier-select-ui-handler.ts +++ b/src/ui/modifier-select-ui-handler.ts @@ -285,13 +285,13 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { ui.showText(options[this.cursor].modifierTypeOption.type.getDescription(this.scene)); } else if (!cursor) { this.cursorObj.setPosition(6, this.lockRarityButtonContainer.visible ? -72 : -60); - ui.showText('Spend money to reroll your item options'); + ui.showText('Spend money to reroll your item options.'); } else if (cursor === 1) { this.cursorObj.setPosition((this.scene.game.canvas.width / 6) - 50, -60); - ui.showText('Transfer a held item from one Pokémon to another'); + ui.showText('Transfer a held item from one Pokémon to another.'); } else { this.cursorObj.setPosition(6, -60); - ui.showText('Lock item rarities on reroll (affects reroll cost)'); + ui.showText('Lock item rarities on reroll (affects reroll cost).'); } return ret;