Repository: jakobhoeg/vscode-pokemon Branch: main Commit: 829500658ab0 Files: 65 Total size: 306.0 KB Directory structure: gitextract_7apv880w/ ├── .eslintrc.json ├── .github/ │ ├── CODE_OF_CONDUCT.md │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── feature_request.md │ └── workflows/ │ ├── ci.yml │ ├── code-quality.yml │ └── gifs.yml ├── .gitignore ├── .husky/ │ └── pre-commit ├── .prettierignore ├── .prettierrc ├── .vscode/ │ ├── extensions.json │ ├── launch.json │ ├── settings.json │ └── tasks.json ├── .vscodeignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── l10n/ │ ├── bundle.l10n.de-DE.json │ ├── bundle.l10n.en-GB.json │ ├── bundle.l10n.en-US.json │ ├── bundle.l10n.fr-FR.json │ ├── bundle.l10n.ja-JP.json │ └── pokemon/ │ ├── de-DE/ │ │ ├── gen1.json │ │ ├── gen2.json │ │ ├── gen3.json │ │ └── gen4.json │ ├── fr-FR/ │ │ ├── gen1.json │ │ ├── gen2.json │ │ ├── gen3.json │ │ └── gen4.json │ └── ja-JP/ │ ├── gen1.json │ ├── gen2.json │ ├── gen3.json │ └── gen4.json ├── media/ │ ├── .gitignore │ ├── pokemon.css │ └── reset.css ├── package.json ├── src/ │ ├── common/ │ │ ├── localize.ts │ │ ├── names.ts │ │ ├── pokemon-data.ts │ │ └── types.ts │ ├── extension/ │ │ └── extension.ts │ ├── panel/ │ │ ├── base-pokemon-type.ts │ │ ├── main.ts │ │ ├── pokemon-collection.ts │ │ ├── pokemon.ts │ │ ├── sequences.ts │ │ └── states.ts │ └── test/ │ ├── gifs.ts │ ├── package.json │ ├── runTest.js │ ├── runTest.ts │ └── suite/ │ ├── index.js │ ├── index.ts │ └── panel.test.ts ├── tsconfig.extension.json ├── tsconfig.json ├── tsconfig.panel.json ├── tsconfig.test.json ├── tsconfig.web.json └── webpack.config.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .eslintrc.json ================================================ { "root": true, "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 6, "sourceType": "module", "project": "./tsconfig.json" }, "plugins": [ "@typescript-eslint", "prettier", "unused-imports" ], "extends": [ "eslint:recommended", "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended" ], "rules": { "@typescript-eslint/naming-convention": "warn", "@typescript-eslint/semi": "warn", "curly": "warn", "eqeqeq": "warn", "no-throw-literal": "warn", "semi": "off", "@typescript-eslint/no-inferrable-types": "off", "no-unused-vars": "error", "no-var": "off", "no-fallthrough": "warn", "unused-imports/no-unused-imports": "error", "prefer-const": "error", "@typescript-eslint/no-non-null-assertion": "warn", "@typescript-eslint/no-floating-promises": "warn", "prettier/prettier": [ "error", { "endOfLine": "auto" } ] }, "ignorePatterns": [ "out", "dist", "node_modules", ".vscode", "src/test" ] } ================================================ FILE: .github/CODE_OF_CONDUCT.md ================================================ The VS Code Pokémon project is dedicated to providing a respectful, harassment-free community for everyone. We do not tolerate harassment or bullying of any community member in any form. This does not only extend to members to local VS Code Pokémon communities, but to anyone who chooses to become involved in the larger VS Code Pokémon community of users, developers, and integrators through events or interactions. Harassment includes offensive verbal/electronic comments related to personal characteristics or choices, sexual images or comments in public or online spaces, deliberate intimidation, bullying, stalking, following, harassing photography or recording, sustained disruption of talks, IRC chats, electronic meetings, physical meetings or other events, inappropriate physical contact, or unwelcome sexual attention. Participants asked to stop any harassing or bullying behavior are expected to comply immediately. If a participant engages in harassing behavior, representatives of the community may take reasonable action they deem appropriate, including warning the offender, expulsion from any VS Code Pokémon event, or expulsion from mailing lists, discussion boards, and other electronic communications channels to resolve the issue. If you are being harassed, notice that someone else is being harassed, or have any other concerns, please act to intercede or ask for help from any member of the VS Code Pokémon community, or organizers/representatives of any physical events put on under the auspices of VS Code Pokémon. This Code of Conduct has been adapted from the [Plone Foundation](http://plone.org/foundation/materials/foundation-resolutions/code-of-conduct) and is licensed under a [Creative Commons Attribution-Share Alike 3.0 Unported license](http://creativecommons.org/licenses/by-sa/3.0/) ================================================ FILE: .github/FUNDING.yml ================================================ github: [jakobhoeg] ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to help us improve title: '' labels: 'bug' assignees: '' --- **Describe the bug** A clear and concise description of what the bug is. **Screenshots** Please send screenshots of the developer console (Right-click > Inspect > Console) on the pages where the bug is occurring. **Additional context** Add any other context about the problem here. ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest an idea for vscode-pokemon title: '' labels: 'feature' assignees: '' --- **Please describe your idea.** A clear and concise description of what the feature would do. **Describe how the idea would be helpful** A clear and concise description of how the feature would be helpful to users. **Additional context** Add any other context or screenshots about the feature request here. ================================================ FILE: .github/workflows/ci.yml ================================================ # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions name: CI on: pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest strategy: matrix: node-version: [20.18.1] steps: - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm ci - run: npm run compile - name: Package VSIX run: npm install -g @vscode/vsce && vsce package - uses: actions/upload-artifact@v4 with: path: '*.vsix' ================================================ FILE: .github/workflows/code-quality.yml ================================================ name: Code Quality on: pull_request: branches: - main jobs: lint-and-format: runs-on: ubuntu-latest name: Lint and Format Check - ${{ github.event.number }} steps: - name: Checkout repository uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: 20 cache: npm - name: Install dependencies run: npm ci - name: Run ESLint run: npm run lint - name: Check formatting with Prettier run: npm run format:check ================================================ FILE: .github/workflows/gifs.yml ================================================ name: Verify Gifs Filename on: pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Verify Gifs Filename run: | npm install npm run compile:test npm run test:gifs ================================================ FILE: .gitignore ================================================ out dist node_modules .vscode-test/ *.vsix .build-out/ coverage/ .nyc_output/ .idea/ media/main-bundle.js .DS_Store ================================================ FILE: .husky/pre-commit ================================================ npx lint-staged ================================================ FILE: .prettierignore ================================================ CHANGELOG.md README.md LICENSE .gitignore .eslintrc.json out media .vscode .dist .out .github tsconfig.json tsconfig.panel.json tsconfig.extension.json tsconfig.test.json tsconfig.web.json webpack.config.js ================================================ FILE: .prettierrc ================================================ { "singleQuote": true, "trailingComma": "all", "semi": true, "printWidth": 80, "tabWidth": 2, "useTabs": false } ================================================ FILE: .vscode/extensions.json ================================================ { // See http://go.microsoft.com/fwlink/?LinkId=827846 // for the documentation about the extensions.json format "recommendations": [ "dbaeumer.vscode-eslint" ] } ================================================ FILE: .vscode/launch.json ================================================ // A launch configuration that compiles the extension and then opens it inside a new window // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 { "version": "0.2.0", "configurations": [ { "name": "Run Extension", "type": "extensionHost", "request": "launch", "args": [ "--extensionDevelopmentPath=${workspaceFolder}" ], "outFiles": [ "${workspaceFolder}/out/**/*.js" ], "preLaunchTask": "${defaultBuildTask}" }, { "name": "Extension Tests", "type": "extensionHost", "request": "launch", "args": [ "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out/test/suite/index" ], "outFiles": [ "${workspaceFolder}/out/test/**/*.js" ], "preLaunchTask": "${defaultBuildTask}" }, { "name": "Run Web Extension in VS Code", "type": "pwa-extensionHost", "debugWebWorkerHost": true, "request": "launch", "args": [ "--extensionDevelopmentPath=${workspaceFolder}", "--extensionDevelopmentKind=web" ], "outFiles": [ "${workspaceFolder}/dist/web/**/*.js" ], "preLaunchTask": "${defaultBuildTask}" }, ] } ================================================ FILE: .vscode/settings.json ================================================ // Place your settings in this file to overwrite default and user settings. { "files.exclude": { "out": false // set this to true to hide the "out" folder with the compiled JS files }, "search.exclude": { "out": true // set this to false to include "out" folder in search results }, // Turn off tsc task auto detection since we have the necessary tasks as npm scripts "typescript.tsc.autoDetect": "off", "nuxt.isNuxtApp": false } ================================================ FILE: .vscode/tasks.json ================================================ // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format { "version": "2.0.0", "tasks": [ { "type": "npm", "script": "watch", "problemMatcher": "$tsc-watch", "isBackground": true, "presentation": { "reveal": "never" }, "group": { "kind": "build", "isDefault": true } } ] } ================================================ FILE: .vscodeignore ================================================ .vscode/** .vscode-test/** out/test/** src/** .gitignore .yarnrc **/tsconfig.json **/.eslintrc.json **/*.map **/*.ts .build-out/ coverage/ docs/ node_modules ================================================ FILE: CHANGELOG.md ================================================ # Change Log All notable changes to the "vscode-pokemon" extension will be documented in this file. ## [4.3.5] - fix: resolve delay when removing more than one pokemon quickly ## [4.3.4] - feat: add shiny configuration option to default Pokemon settings - fix: prevent spawning empty Pokémon collection on session start ## [4.3.3] - fix: improve session handling and normalize pokemon counter ## [4.3.2] - fix: add back accidentally removed "remove-all" command ## [4.3.1] - feat: add multi-language support - fix: add missing Nidoqueen & Rotom sprites ## [4.2.0] - feat: add shiny sprites & spawn rate for gen 1-4 ## [4.1.1] - fix: optimize remove Pokemon method ## [4.1.0] - feat: added code-quality GitHub Action - chore: formatted the whole codebase with Prettier - chore: enforced ESlint rules on commit ## [4.0.1] - feat: change Pokémon speed depending on size ## [4.0.0] - feat: added gen 4 pokemon - feat: add missing forms for Pichu, Heracross, and Wobbuffet ## [3.5.0] - feat: Added Unown characters in Gen 2 - fix: Corphish in pokemon-data.ts - fix: Swipe state bug making everything stand still and not work anymore - fix: handle cancellation of Pokemon spawning when no name is entered ## [3.4.0] - feat: Pokémon spawn animation via Pokéball ## [3.3.0] - feat: add default pokemon configurable through settings.json ## [3.2.2] - fix: issue when adding pokemon - fix: update keybindings to make "remove all" work ## [3.2.1] - feat: add better search functionality - feat: add hotkeys ## [3.1.1] - chore: update readme ## [3.1.0] - fix: stop randomly and change direction - fix: make default size medium ## [3.0.1] - fix: pixelate bubbles ## [3.0.0] - feat: add generation 3 Pokémon ## [2.0.3] - fix: add Celebi + fix Ho-Oh id ## [2.0.2] - fix: use pixelate image rendering ## [2.0.1] - fix: Entei typo ## [2.0.0] - feat: add generation 2 Pokemon ## [1.1.0] - feat: add functionality for adding a random Pokemon ## [1.0.2] - fix: added missing Victreebel & Omastar ## [1.0.1] - Bump version to reflex changes to readme ## [1.0.0] - Added all 1st generation Pokémon. ================================================ FILE: LICENSE ================================================ All image contents within are Copyright The Pokémon Company. Creative Commons Legal Code CC0 1.0 Universal CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED HEREUNDER. Statement of Purpose The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: i. the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; ii. moral rights retained by the original author(s) and/or performer(s); iii. publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; iv. rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; v. rights protecting the extraction, dissemination, use and reuse of data in a Work; vi. database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and vii. other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 4. Limitations and Disclaimers. a. No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. b. Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. c. Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. d. Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. ================================================ FILE: README.md ================================================
# VS Code Pokémon ![icon](https://github.com/jakobhoeg/vscode-pokemon/raw/main/icon.png)

Puts cute Pokémon in your code editor to boost productivity ✨

Report a Bug · Request feature

![Visual Studio Marketplace Version](https://img.shields.io/visual-studio-marketplace/v/jakobhoeg.vscode-pokemon) ![Visual Studio Marketplace Installs](https://img.shields.io/visual-studio-marketplace/i/jakobhoeg.vscode-pokemon) ![Visual Studio Marketplace Downloads](https://img.shields.io/visual-studio-marketplace/d/jakobhoeg.vscode-pokemon)
Shows gif in dark or light mode
Seen used by engineers at [Microsoft](https://code.visualstudio.com/updates/v1_101#_chat-ux-improvements)!
## 💖 Support If you enjoy this project, please consider supporting me. Manually creating the `.gif` files for each sprite takes a lot of time and effort. Your sponsorship helps me dedicate more energy to improve and expand the project. [![GitHub Sponsor](https://img.shields.io/badge/Sponsor-❤-blue?style=flat&logo=github)](https://github.com/sponsors/jakobhoeg) ## Installation Install this extension from the [VS Code marketplace](https://marketplace.visualstudio.com/items?itemName=jakobhoeg.vscode-pokemon) or the [Open VSX Registry](https://open-vsx.org/extension/jakobhoeg/vscode-pokemon). ![Default view](https://github.com/jakobhoeg/vscode-pokemon/raw/main/install.png) OR With VS Code open, search for `vscode-pokemon` in the extension panel (`Ctrl+Shift+X` on Windows/Linux or `Cmd(⌘)+Shift+X` on MacOS) and click install. OR With VS Code open, launch VS Code Quick Open (`Ctrl+P` on Windows/Linux or `Cmd(⌘)+P` on MacOS), paste the following command, and press enter. `ext install jakobhoeg.vscode-pokemon` ## Using VS Code Pokémon After installing, open the command palette with `Ctrl+Shift+P` on Windows/Linux or `Cmd(⌘)+Shift+P` on MacOS. Run the "Start Pokemon coding session" command (`vscode-pokemon.start`) to see a Bulbasaur in VS Code: ![Default view](https://github.com/jakobhoeg/vscode-pokemon/raw/main/usage.png) Enjoy interacting with your favourite Pokémon! ## Keyboard Shortcuts VS Code Pokémon comes with default keyboard shortcuts to make managing your Pokémon quick and easy: ![Keybindings](https://github.com/jakobhoeg/vscode-pokemon/raw/main/keybindings.png) ### Configuring Keyboard Shortcuts You can customize these shortcuts to match your preferences: 1. Open the command palette (`Ctrl+Shift+P` on Windows/Linux or `Cmd(⌘)+Shift+P` on MacOS) 2. Run the **`Pokemon Coding: Configure keybindings`** command 3. Select the command you want to customize 4. VS Code will open the Keyboard Shortcuts editor filtered to that command 5. Click the pencil icon next to the command and press your desired key combination ## Changing settings Open the setting panel with Ctrl+, on Windows/Linux or Cmd(⌘)+, on MacOS. In the search bar, enter “vscode-pokemon" to see all available options. Set the size and position of the extension. ### Default Pokémon You can configure specific Pokémon to automatically appear when you first start using the extension. This is useful for setting up your preferred team without having to manually spawn them when you open new windows. To configure default Pokémon, add the following to your `settings.json`: ```json { "vscode-pokemon.defaultPokemon": [ { "type": "pikachu", "name": "Sparky" }, { "type": "charizard", "name": "Flame" }, { "type": "articuno" } ] } ``` - **`type`** (required): The Pokémon species (e.g., `"pikachu"`, `"charizard"`, `"mewtwo"`) - **`name`** (optional): A custom name for your Pokémon. If not provided, a random name will be assigned - **`shiny`** (optional): Determines if the Pokémon is shiny, if not set will use `vscode-pokemon.shinyOdds` setting. **Note:** The extension automatically saves your current Pokémon between sessions. The `defaultPokemon` setting is only used when: - You start the extension for the first time - You open a new windows/repository - You have removed all Pokémon (no saved session exists) To reset to your default Pokémon, use the "Remove all pokemon" command and restart VS Code. ### Pokémon Language You can customize the language used for Pokémon names. The extension supports official Pokémon languages: English (US), French, German, and Japanese. #### Using the Command 1. Open the command palette (`Ctrl+Shift+P` on Windows/Linux or `Cmd(⌘)+Shift+P` on MacOS) 2. Run the **`Pokemon Coding: Change Pokemon language`** command 3. Select your preferred language from the list #### Using Settings You can also configure the language directly in your `settings.json`: ```json { "vscode-pokemon.pokemonLanguage": "fr-FR" } ``` Available options: - **`auto`** (default): Automatically uses VS Code's language setting - **`en-US`**: English (US) names - **`fr-FR`**: French names (e.g., "Bulbizarre", "Salamèche", "Dracaufeu") - **`de-DE`**: German names (e.g., "Bisasam", "Glumanda", "Glurak") - **`ja-JP`**: Japanese names (e.g., "フシギダネ", "ヒトカゲ", "リザードン") **Note:** The language setting applies to all Pokémon names throughout the extension, including in the spawn selection menu, roll-call, and export features. Translations are available for all Pokémon from Generations 1, 2, 3, and 4. ## Features Extracting and creating .gif files involves quite a bit of tedious manual work, but I’ll aim to add Gen 5 when possible. ## Credits ### Sprite Sources - Pokemon Sprites: © The Pokémon Company / Nintendo / Game Freak - The sprites are used for non-commercial, fan project purposes only - Original sprite artwork belongs to the respective copyright holders ### Acknowledgments - All sprites are property of their original creators - This repository is a fan project and is not affiliated with Nintendo, The Pokémon Company, or Game Freak This repository is inspired by and based on [vscode-pets](https://github.com/tonybaloney/vscode-pets) by [tonybaloney](https://github.com/tonybaloney). ================================================ FILE: l10n/bundle.l10n.de-DE.json ================================================ { "Spawn Pokemon": "Pokemon erscheinen lassen", "Pokemon Panel": "Pokemon-Panel", "Pokemon language changed to {0}. The change will persist after restart.": "Pokemon-Sprache wurde auf {0} geändert. Die Änderung bleibt nach dem Neustart erhalten.", "Select a Pokemon": "Wähle ein Pokemon", "Select a color": "Wähle eine Farbe", "Select language for Pokemon names": "Sprache für Pokemon-Namen auswählen", "Select a generation or start typing to search for a Pokemon...": "Wähle eine Generation oder tippe, um nach einem Pokemon zu suchen...", "Select the Pokemon to remove.": "Wähle das Pokemon zum Entfernen.", "Select a command to configure its keybinding": "Wähle einen Befehl, um seine Tastenkombination zu konfigurieren", "Leave blank for a random name": "Leer lassen für einen zufälligen Namen", "Name your Pokemon": "Benenne dein Pokemon", "Cancelled Spawning Pokemon": "Pokemon-Erscheinen abgebrochen", "A Pokemon Playground has been created. You can now use the \"Spawn Additional Pokemon\" Command to add more Pokemon.": "Ein Pokemon-Center wurde erstellt. Du kannst jetzt den Befehl \"Zusätzliches Pokemon erscheinen lassen\" verwenden, um weitere Pokemon hinzuzufügen.", "A Pokemon Playground has been created. You can now use the \"Remove All Pokemon\" Command to remove all Pokemon.": "Ein Pokemon-Center wurde erstellt. Du kannst jetzt den Befehl \"Alle Pokemon entfernen\" verwenden, um alle Pokemon zu entfernen.", "Generation {0}": "Generation {0}", "Browse Gen {0} Pokemon": "Gen {0} Pokemon durchsuchen", "Generations": "Generationen", "Results": "Ergebnisse", "Current": "Aktuell", "Use VS Code language": "VS Code-Sprache verwenden", "English names": "Englische Namen", "French names": "Französische Namen", "German names": "Deutsche Namen", "Japanese names": "Japanische Namen", "Spawn additional pokemon": "Zusätzliches Pokemon erscheinen lassen", "Spawn random pokemon": "Zufälliges Pokemon erscheinen lassen", "Remove pokemon": "Pokemon entfernen", "Remove all pokemon": "Alle Pokemon entfernen", "There are no pokemon to remove.": "Es gibt keine Pokemon zum Entfernen.", "You must have a folder or workspace open to export pokemonCollection.": "Du musst einen Ordner oder Arbeitsbereich geöffnet haben, um die Pokemon-Sammlung zu exportieren.", "Failed to import pokemon: {0}": "Fehler beim Importieren von Pokemon: {0}", "default": "Standard", "shiny": "Schillernd" } ================================================ FILE: l10n/bundle.l10n.en-GB.json ================================================ { "Spawn Pokemon": "Spawn Pokemon", "Pokemon Panel": "Pokemon Panel", "Pokemon language changed to {0}. The change will persist after restart.": "Pokemon language changed to {0}. The change will persist after restart.", "Select a Pokemon": "Select a Pokemon", "Select a color": "Select a colour", "Select language for Pokemon names": "Select language for Pokemon names", "Select a generation or start typing to search for a Pokemon...": "Select a generation or start typing to search for a Pokemon...", "Select the Pokemon to remove.": "Select the Pokemon to remove.", "Select a command to configure its keybinding": "Select a command to configure its keybinding", "Leave blank for a random name": "Leave blank for a random name", "Name your Pokemon": "Name your Pokemon", "Cancelled Spawning Pokemon": "Cancelled Spawning Pokemon", "A Pokemon Playground has been created. You can now use the \"Spawn Additional Pokemon\" Command to add more Pokemon.": "A Pokemon Center has been created. You can now use the \"Spawn Additional Pokemon\" command to add more Pokemon.", "A Pokemon Playground has been created. You can now use the \"Remove All Pokemon\" Command to remove all Pokemon.": "A Pokemon Center has been created. You can now use the \"Remove All Pokemon\" command to remove all Pokemon.", "Generation {0}": "Generation {0}", "Browse Gen {0} Pokemon": "Browse Gen {0} Pokemon", "Generations": "Generations", "Results": "Results", "Current": "Current", "Use VS Code language": "Use VS Code language", "English names": "English names", "French names": "French names", "German names": "German names", "Japanese names": "Japanese names", "Spawn additional pokemon": "Spawn additional pokemon", "Spawn random pokemon": "Spawn random pokemon", "Remove pokemon": "Remove pokemon", "Remove all pokemon": "Remove all pokemon", "There are no pokemon to remove.": "There are no pokemon to remove.", "You must have a folder or workspace open to export pokemonCollection.": "You must have a folder or workspace open to export pokemonCollection.", "Failed to import pokemon: {0}": "Failed to import pokemon: {0}", "default": "Default", "shiny": "Shiny" } ================================================ FILE: l10n/bundle.l10n.en-US.json ================================================ { "Spawn Pokemon": "Spawn Pokemon", "Pokemon Panel": "Pokemon Panel", "Pokemon language changed to {0}. The change will persist after restart.": "Pokemon language changed to {0}. The change will persist after restart.", "Select a Pokemon": "Select a Pokemon", "Select a color": "Select a color", "Select language for Pokemon names": "Select language for Pokemon names", "Select a generation or start typing to search for a Pokemon...": "Select a generation or start typing to search for a Pokemon...", "Select the Pokemon to remove.": "Select the Pokemon to remove.", "Select a command to configure its keybinding": "Select a command to configure its keybinding", "Leave blank for a random name": "Leave blank for a random name", "Name your Pokemon": "Name your Pokemon", "Cancelled Spawning Pokemon": "Cancelled Spawning Pokemon", "A Pokemon Playground has been created. You can now use the \"Spawn Additional Pokemon\" Command to add more Pokemon.": "A Pokemon Center has been created. You can now use the \"Spawn Additional Pokemon\" command to add more Pokemon.", "A Pokemon Playground has been created. You can now use the \"Remove All Pokemon\" Command to remove all Pokemon.": "A Pokemon Center has been created. You can now use the \"Remove All Pokemon\" command to remove all Pokemon.", "Generation {0}": "Generation {0}", "Browse Gen {0} Pokemon": "Browse Gen {0} Pokemon", "Generations": "Generations", "Results": "Results", "Current": "Current", "Use VS Code language": "Use VS Code language", "English names": "English names", "French names": "French names", "German names": "German names", "Japanese names": "Japanese names", "Spawn additional pokemon": "Spawn additional pokemon", "Spawn random pokemon": "Spawn random pokemon", "Remove pokemon": "Remove pokemon", "Remove all pokemon": "Remove all pokemon", "There are no pokemon to remove.": "There are no pokemon to remove.", "You must have a folder or workspace open to export pokemonCollection.": "You must have a folder or workspace open to export pokemonCollection.", "Failed to import pokemon: {0}": "Failed to import pokemon: {0}", "default": "Default", "shiny": "Shiny" } ================================================ FILE: l10n/bundle.l10n.fr-FR.json ================================================ { "A Pokemon Playground has been created. You can now use the \"Remove All Pokemon\" Command to remove all Pokemon.": "Un Centre Pokémon a été créé. Vous pouvez maintenant utiliser la commande \"Retirer tous les Pokémon\" pour retirer tous les Pokémon.", "A Pokemon Playground has been created. You can now use the \"Spawn Additional Pokemon\" Command to add more Pokemon.": "Un Centre Pokémon a été créé. Vous pouvez maintenant utiliser la commande \"Faire apparaître un Pokémon supplémentaire\" pour ajouter plus de Pokémon.", "Browse Gen {0} Pokémon": "Parcourir les Pokémon de Gen {0}", "Cancelled Spawning Pokemon": "Apparition de Pokémon annulée", "Current": "Actuel", "English names": "Noms anglais", "Failed to import pokemon: {0}": "Échec de l'importation du Pokémon : {0}", "French names": "Noms français", "Generation {0}": "Génération {0}", "Generations": "Générations", "German names": "Noms allemands", "Japanese names": "Noms japonais", "Leave blank for a random name": "Laisser vide pour un nom aléatoire", "Name your Pokemon": "Nommer votre Pokémon", "Name your Pokémon": "Nommer votre Pokémon", "Pokemon Panel": "Panneau Pokémon", "Pokemon language changed to {0}. The change will persist after restart.": "Langue des Pokémon changée en {0}. Le changement persistera après redémarrage.", "Remove all pokemon": "Retirer tous les Pokémon", "Remove pokemon": "Retirer un Pokémon", "Results": "Résultats", "Select a Pokemon": "Sélectionner un Pokémon", "Select a Pokémon": "Sélectionner un Pokémon", "Select a color": "Sélectionner une couleur", "Select a command to configure its keybinding": "Sélectionner une commande pour configurer son raccourci clavier", "Select a generation or start typing to search for a Pokémon...": "Sélectionner une génération ou commencer à taper pour rechercher un Pokémon...", "Select language for Pokemon names": "Sélectionner la langue pour les noms de Pokémon", "Select the Pokemon to remove.": "Sélectionner le Pokémon à retirer.", "Spawn Pokemon": "Apparition d'un Pokémon", "Spawn additional pokemon": "Faire apparaître un Pokémon supplémentaire", "Spawn random pokemon": "Faire apparaître un Pokémon aléatoire", "There are no pokemon to remove.": "Il n'y a aucun Pokémon à retirer.", "Use VS Code language": "Utiliser la langue de VS Code", "You must have a folder or workspace open to export pokemonCollection.": "Vous devez avoir un dossier ou un espace de travail ouvert pour exporter la collection de Pokémon.", "default": "Par défaut", "shiny": "Chromatique" } ================================================ FILE: l10n/bundle.l10n.ja-JP.json ================================================ { "Spawn Pokemon": "ポケモンを出現させる", "Pokemon Panel": "ポケモンパネル", "Pokemon language changed to {0}. The change will persist after restart.": "ポケモンの言語が{0}に変更されました。この変更は再起動後も保持されます。", "Select a Pokemon": "ポケモンを選択", "Select a color": "色を選択", "Select language for Pokemon names": "ポケモン名の言語を選択", "Select a generation or start typing to search for a Pokemon...": "世代を選択するか、ポケモンを検索するために入力を開始してください...", "Select the Pokemon to remove.": "削除するポケモンを選択してください。", "Select a command to configure its keybinding": "キーバインドを設定するコマンドを選択", "Leave blank for a random name": "ランダムな名前の場合は空白のまま", "Name your Pokemon": "ポケモンに名前を付ける", "Cancelled Spawning Pokemon": "ポケモンの出現をキャンセルしました", "A Pokemon Playground has been created. You can now use the \"Spawn Additional Pokemon\" Command to add more Pokemon.": "ポケモンセンターが作成されました。これで「追加のポケモンを出現させる」コマンドを使用して、さらにポケモンを追加できます。", "A Pokemon Playground has been created. You can now use the \"Remove All Pokemon\" Command to remove all Pokemon.": "ポケモンセンターが作成されました。これで「すべてのポケモンを削除」コマンドを使用して、すべてのポケモンを削除できます。", "Generation {0}": "第{0}世代", "Browse Gen {0} Pokemon": "第{0}世代のポケモンを閲覧", "Generations": "世代", "Results": "結果", "Current": "現在", "Use VS Code language": "VS Codeの言語を使用", "English names": "英語名", "French names": "フランス語名", "German names": "ドイツ語名", "Japanese names": "日本語名", "Spawn additional pokemon": "追加のポケモンを出現させる", "Spawn random pokemon": "ランダムなポケモンを出現させる", "Remove pokemon": "ポケモンを削除", "Remove all pokemon": "すべてのポケモンを削除", "There are no pokemon to remove.": "削除するポケモンがありません。", "You must have a folder or workspace open to export pokemonCollection.": "ポケモンコレクションをエクスポートするには、フォルダーまたはワークスペースを開いている必要があります。", "Failed to import pokemon: {0}": "ポケモンのインポートに失敗しました:{0}", "default": "デフォルト", "shiny": "色違い" } ================================================ FILE: l10n/pokemon/de-DE/gen1.json ================================================ { "abra": "Abra", "aerodactyl": "Aerodactyl", "alakazam": "Simsala", "arbok": "Arbok", "arcanine": "Arkani", "articuno": "Arktos", "beedrill": "Bibor", "bellsprout": "Knofensa", "blastoise": "Turtok", "bulbasaur": "Bisasam", "butterfree": "Smettbo", "caterpie": "Raupy", "chansey": "Chaneira", "charizard": "Glurak", "charmander": "Glumanda", "charmeleon": "Glutexo", "clefable": "Pixi", "clefairy": "Piepi", "cloyster": "Austos", "cubone": "Tragosso", "dewgong": "Jugong", "diglett": "Digda", "ditto": "Ditto", "dodrio": "Dodri", "doduo": "Dodu", "dragonair": "Dragonir", "dragonite": "Dragoran", "dratini": "Dratini", "drowzee": "Traumato", "dugtrio": "Digdri", "eevee": "Evoli", "ekans": "Rettan", "electabuzz": "Elektek", "electrode": "Lektrobal", "exeggcute": "Owei", "exeggutor": "Kokowei", "farfetchd": "Porenta", "fearow": "Iarbok", "flareon": "Flamara", "gastly": "Nebulak", "gengar": "Gengar", "geodude": "Kleinstein", "gloom": "Duflor", "golbat": "Golbat", "goldeen": "Goldini", "golduck": "Entoron", "golem": "Geowaz", "graveler": "Georok", "grimer": "Sleima", "growlithe": "Fukano", "gyarados": "Garados", "haunter": "Alpollo", "hitmonchan": "Nockchan", "hitmonlee": "Kicklee", "horsea": "Seeper", "hypno": "Hypno", "ivysaur": "Bisaknosp", "jigglypuff": "Pummeluff", "jolteon": "Blitza", "jynx": "Rossana", "kabuto": "Kabuto", "kabutops": "Kabutops", "kadabra": "Kadabra", "kakuna": "Kokuna", "kangaskhan": "Kangama", "kingler": "Kingler", "koffing": "Smogon", "krabby": "Krabby", "lapras": "Lapras", "lickitung": "Schlurp", "machamp": "Machomei", "machoke": "Maschock", "machop": "Machollo", "magikarp": "Karpador", "magmar": "Magmar", "magnemite": "Magnetilo", "magneton": "Magneton", "mankey": "Menki", "marowak": "Knogga", "meowth": "Mauzi", "metapod": "Safcon", "mew": "Mew", "mewtwo": "Mewtu", "moltres": "Lavados", "mrmime": "Pantimos", "muk": "Sleimok", "nidoking": "Nidoking", "nidoqueen": "Nidoqueen", "nidoran_female": "Nidoran♀", "nidoran_male": "Nidoran♂", "nidorina": "Nidorina", "nidorino": "Nidorino", "ninetales": "Vulnona", "oddish": "Myrapla", "omanyte": "Amonitas", "omastar": "Amoroso", "onix": "Onix", "paras": "Paras", "parasect": "Parasek", "persian": "Snobilikat", "pidgeot": "Tauboss", "pidgeotto": "Tauboga", "pidgey": "Taubsi", "pikachu": "Pikachu", "pikachu_female": "Pikachu (Weiblich)", "pinsir": "Pinsir", "poliwag": "Quapsel", "poliwhirl": "Quaputzi", "poliwrath": "Quappo", "ponyta": "Ponita", "porygon": "Porygon", "primeape": "Rasaff", "psyduck": "Enton", "raichu": "Raichu", "rapidash": "Gallopa", "raticate": "Rattikarl", "rattata": "Rattfratz", "rhydon": "Rizeros", "rhyhorn": "Rihorn", "sandshrew": "Sandan", "sandslash": "Sandamer", "scyther": "Sichlor", "seadra": "Seemon", "seaking": "Golking", "seel": "Jurob", "shellder": "Muschas", "slowbro": "Lahmus", "slowpoke": "Flegmon", "snorlax": "Relaxo", "spearow": "Habitak", "squirtle": "Schiggy", "starmie": "Starmie", "staryu": "Sterndu", "tangela": "Tangela", "tauros": "Tauros", "tentacool": "Tentacha", "tentacruel": "Tentoxa", "vaporeon": "Aquana", "venomoth": "Omot", "venonat": "Bluzuk", "venusaur": "Bisaflor", "venusaur_female": "Bisaflor (Weiblich)", "victreebel": "Sarzenia", "vileplume": "Giflor", "voltorb": "Voltobal", "vulpix": "Vulpix", "wartortle": "Schillok", "weedle": "Hornliu", "weepinbell": "Ultrigaria", "weezing": "Smogmog", "wigglytuff": "Knuddeluff", "zapdos": "Zapdos", "zubat": "Zubat" } ================================================ FILE: l10n/pokemon/de-DE/gen2.json ================================================ { "aipom": "Griffel", "ampharos": "Ampharos", "ariados": "Ariados", "azumarill": "Azumarill", "bayleef": "Lorblatt", "bellossom": "Blubella", "blissey": "Heiteira", "celebi": "Celebi", "chikorita": "Endivie", "chinchou": "Lampi", "cleffa": "Pii", "corsola": "Corasonn", "crobat": "Iksbat", "croconaw": "Tyracroc", "cyndaquil": "Feurigel", "delibird": "Botogel", "donphan": "Donphan", "dunsparce": "Dummisel", "elekid": "Elekid", "entei": "Entei", "espeon": "Psiana", "feraligatr": "Impergator", "flaaffy": "Waaty", "forretress": "Forstellka", "furret": "Wiesenior", "girafarig": "Girafarig", "gligar": "Skorgla", "granbull": "Granbull", "heracross": "Skaraborn", "heracross_male": "Skaraborn (Männlich)", "heracross_female": "Skaraborn (Weiblich)", "hitmontop": "Kapoera", "hooh": "Ho-Oh", "hoothoot": "Hoothoot", "hoppip": "Hoppspross", "houndoom": "Hundemon", "houndour": "Hunduster", "igglybuff": "Fluffeluff", "jumpluff": "Papungha", "kingdra": "Seedraking", "lanturn": "Lanturn", "larvitar": "Larvitar", "ledian": "Ledian", "ledyba": "Ledyba", "lugia": "Lugia", "magby": "Magby", "magcargo": "Magcargo", "mantine": "Mantax", "mareep": "Voltilamm", "marill": "Marill", "meganium": "Meganie", "meganium_female": "Meganie (Weiblich)", "miltank": "Miltank", "misdreavus": "Traunfugil", "murkrow": "Kramurx", "natu": "Natu", "noctowl": "Noctuh", "octillery": "Octillery", "phanpy": "Phanpy", "pichu": "Pichu", "piloswine": "Keifel", "pineco": "Tannza", "politoed": "Quaxo", "porygon2": "Porygon2", "pupitar": "Pupitar", "quagsire": "Morlord", "quilava": "Igelavar", "qwilfish": "Baldorfish", "raikou": "Raikou", "remoraid": "Remoraid", "scizor": "Scherox", "sentret": "Wiesor", "shuckle": "Pottrott", "skarmory": "Panzaeron", "skiploom": "Hubelupf", "slowking": "Laschoking", "slugma": "Schneckmag", "smeargle": "Farbeagle", "smoochum": "Rossana", "sneasel": "Sniebel", "snubbull": "Snubbull", "spinarak": "Webarak", "stantler": "Damhirplex", "steelix": "Stahlos", "steelix_female": "Stahlos (Weiblich)", "sudowoodo": "Mogelbaum", "suicune": "Suicune", "sunflora": "Sonnflora", "sunkern": "Sonnkern", "swinub": "Quiekel", "teddiursa": "Teddiursa", "togepi": "Togepi", "togetic": "Togetic", "totodile": "Karnimani", "typhlosion": "Tornupto", "tyranitar": "Despotar", "tyrogue": "Rabauz", "umbreon": "Nachtara", "ursaring": "Ursaring", "wobbuffet": "Woingenau", "wobbuffet_male": "Woingenau (Männlich)", "wobbuffet_female": "Woingenau (Weiblich)", "wooper": "Felino", "xatu": "Xatu", "yanma": "Yanma" } ================================================ FILE: l10n/pokemon/de-DE/gen3.json ================================================ { "absol": "Absol", "aggron": "Stolloss", "altaria": "Altaria", "anorith": "Anorith", "armaldo": "Armaldo", "aron": "Stollunior", "azurill": "Azurill", "bagon": "Kindwurm", "baltoy": "Puppance", "banette": "Zuppetta", "barboach": "Schmerbe", "beautifly": "Papinella", "beldum": "Tanhel", "blaziken": "Lohgock", "breloom": "Kapilz", "cacnea": "Tuska", "cacturne": "Noktuska", "camerupt": "Camerupt", "carvanha": "Kanivanha", "cascoon": "Panekon", "castform": "Formeo", "chimecho": "Palimpalim", "clamperl": "Perlu", "claydol": "Lepumentas", "combusken": "Jungglut", "corpish": "Krebscorps", "cradily": "Wielie", "crawdaunt": "Krebutack", "delcatty": "Enekoro", "deoxys": "Deoxys", "deoxys_attack": "Deoxys (Angriff)", "deoxys_defense": "Deoxys (Verteidigung)", "deoxys_speed": "Deoxys (Initiative)", "dusclops": "Zwirrklop", "duskull": "Zwirrlicht", "dustox": "Pudox", "electrike": "Frizelbliz", "exploud": "Krawumms", "feebas": "Barschwa", "flygon": "Libelldra", "gardevoir": "Guardevoir", "glalie": "Firnontor", "gorebyss": "Saganabyss", "groudon": "Groudon", "grovyle": "Reptain", "grumpig": "Groink", "gulpin": "Schluppuck", "hariyama": "Hariyama", "huntail": "Aalabyss", "illumise": "Illumise", "jirachi": "Jirachi", "kecleon": "Kecleon", "kirlia": "Kirlia", "kyogre": "Kyogre", "lairon": "Stollrak", "latias": "Latias", "latios": "Latios", "lileep": "Liliep", "linoone": "Geradaks", "lombre": "Lombrero", "lotad": "Loturzel", "loudred": "Krakeelo", "ludicolo": "Kappalores", "lunatone": "Lunastein", "luvdisc": "Liebiskus", "makuhita": "Makuhita", "manectric": "Voltenso", "marshtomp": "Moorabbel", "masquerain": "Maskeregen", "mawile": "Flunkifer", "medicham": "Meditalis", "meditite": "Meditie", "metagross": "Metagross", "metang": "Metang", "mightyena": "Mightyena", "milotic": "Milotic", "minun": "Minun", "mudkip": "Hydropi", "nincada": "Nincada", "ninjask": "Ninjask", "nosepass": "Nasgnet", "numel": "Camaub", "nuzleaf": "Blanas", "pelipper": "Pelipper", "plusle": "Plusle", "poochyena": "Fiffyen", "ralts": "Trasla", "rayquaza": "Rayquaza", "regice": "Regice", "regirock": "Regirock", "registeel": "Registeel", "relicanth": "Relicanth", "roselia": "Roselia", "sableye": "Zobiris", "salamence": "Brutalanda", "sceptile": "Gewaldro", "sealeo": "Seejong", "seedot": "Samurzel", "seviper": "Vipitis", "sharpedo": "Tohaido", "shedinja": "Ninjatom", "shelgon": "Draschel", "shiftry": "Tengulist", "shroomish": "Knilz", "shuppet": "Shuppet", "silcoon": "Schaloko", "skitty": "Eneco", "slaking": "Letarking", "slakoth": "Bummelz", "snorunt": "Schneppke", "solrock": "Sonnfel", "spheal": "Seemops", "spinda": "Pandir", "spoink": "Spoink", "surskit": "Gehweiher", "swablu": "Wablu", "swalot": "Schlukwech", "swampert": "Sumpex", "swellow": "Schwalboss", "taillow": "Schwalbini", "torchic": "Flemmli", "torkoal": "Qurtel", "trapinch": "Knacklion", "treecko": "Geckarbor", "tropius": "Tropius", "vibrava": "Vibrava", "vigoroth": "Muntier", "volbeat": "Volbeat", "wailmer": "Wailmer", "wailord": "Wailord", "walrein": "Walraisa", "whiscash": "Welsar", "whismur": "Flurmel", "wingull": "Wingull", "wurmple": "Waumpel", "wynaut": "Isso", "zangoose": "Zangoose", "zigzagoon": "Zigzachs" } ================================================ FILE: l10n/pokemon/de-DE/gen4.json ================================================ { "turtwig": "Chelast", "grotle": "Chelcarain", "torterra": "Chelterrar", "chimchar": "Panflam", "monferno": "Panpyro", "infernape": "Panferno", "piplup": "Plinfa", "prinplup": "Pliprin", "empoleon": "Impoleon", "starly": "Staralili", "staravia": "Staravia", "staraptor": "Staraptor", "bidoof": "Bidiza", "bibarel": "Bidifas", "kricketot": "Zirpurze", "kricketune": "Zirpeise", "shinx": "Sheinux", "luxio": "Luxio", "luxray": "Luxtra", "budew": "Knospi", "roserade": "Roserade", "cranidos": "Koknodon", "rampardos": "Rameidon", "shieldon": "Schilterus", "bastiodon": "Bollterus", "burmy_plant": "Burmy (Pflanze)", "burmy_sandy": "Burmy (Sand)", "burmy_trash": "Burmy (Müll)", "wormadam_plant": "Burmadame (Pflanze)", "wormadam_sandy": "Burmadame (Sand)", "wormadam_trash": "Burmadame (Müll)", "mothim": "Moterpel", "combee_male": "Wadribie (Männlich)", "combee_female": "Wadribie (Weiblich)", "vespiquen": "Honweisel", "pachirisu": "Pachirisu", "buizel": "Bamelin", "floatzel": "Bojelin", "cherubi": "Kikugi", "cherrim": "Kinoso", "shellos_west": "Schalellos (West)", "shellos_east": "Schalellos (Ost)", "gastrodon_west": "Gastrodon (West)", "gastrodon_east": "Gastrodon (Ost)", "ambipom": "Ambidiffel", "drifloon": "Driftlon", "drifblim": "Drifzepeli", "buneary": "Haspiror", "lopunny": "Schlapor", "mismagius": "Traunmagil", "honchkrow": "Kramshef", "glameow": "Charmian", "purugly": "Shnurgarst", "chingling": "Klingplim", "stunky": "Skunkapuh", "skuntank": "Skuntank", "bronzor": "Bronzel", "bronzong": "Bronzong", "bonsly": "Mobai", "mrmime": "Pantimos", "happiny": "Wonneira", "chatot": "Plaudagei", "spiritomb": "Kryppuk", "gible": "Kaumalat", "gible_female": "Kaumalat (Weiblich)", "gabite": "Knarksel", "gabite_female": "Knarksel (Weiblich)", "garchomp": "Knakrack", "garchomp_female": "Knakrack (Weiblich)", "munchlax": "Mampfaxo", "riolu": "Riolu", "lucario": "Lucario", "hippopotas_male": "Hippopotas (Männlich)", "hippopotas_female": "Hippopotas (Weiblich)", "hippowdon_male": "Hippoterus (Männlich)", "hippowdon_female": "Hippoterus (Weiblich)", "skorupi": "Pionskora", "drapion": "Piondragi", "croagunk": "Glibunkel", "toxicroak": "Toxiquak", "carnivine": "Venuflibis", "finneon": "Finneon", "lumineon": "Lumineon", "mantyke": "Mantirps", "snover": "Shnebedeck", "abomasnow": "Rexblisar", "weavile": "Snibunna", "magnezone": "Magnezone", "lickilicky": "Schlurplek", "rhyperior": "Rihornior", "tangrowth": "Tangoloss", "electivire": "Elevoltek", "magmortar": "Magbrant", "togekiss": "Togekiss", "yanmega": "Yanmega", "leafeon": "Folipurba", "glaceon": "Glaziola", "gliscor": "Skorgro", "mamoswine": "Mamutel", "porygon_z": "Porygon-Z", "gallade": "Galagladi", "probopass": "Voluminas", "dusknoir": "Zwirrfinst", "froslass": "Frosdedje", "rotom": "Rotom", "rotom_heat": "Rotom (Hitze)", "rotom_wash": "Rotom (Wasch)", "rotom_frost": "Rotom (Frost)", "rotom_fan": "Rotom (Wirbel)", "rotom_mow": "Rotom (Schneid)", "uxie": "Selfe", "mesprit": "Vesprit", "azelf": "Tobutz", "dialga": "Dialga", "palkia": "Palkia", "heatran": "Heatran", "regigigas": "Regigigas", "giratina": "Giratina", "giratina_origin": "Giratina (Urform)", "cresselia": "Cresselia", "phione": "Phione", "manaphy": "Manaphy", "darkrai": "Darkrai", "shaymin": "Shaymin", "shaymin_sky": "Shaymin (Zenitform)", "arceus": "Arceus", "arceus_bug": "Arceus (Käfer)", "arceus_dark": "Arceus (Unlicht)", "arceus_dragon": "Arceus (Drache)", "arceus_electric": "Arceus (Elektro)", "arceus_fighting": "Arceus (Kampf)", "arceus_fire": "Arceus (Feuer)", "arceus_flying": "Arceus (Flug)", "arceus_ghost": "Arceus (Geist)", "arceus_grass": "Arceus (Pflanze)", "arceus_ground": "Arceus (Boden)", "arceus_ice": "Arceus (Eis)", "arceus_poison": "Arceus (Gift)", "arceus_psychic": "Arceus (Psycho)", "arceus_rock": "Arceus (Gestein)", "arceus_steel": "Arceus (Stahl)", "arceus_water": "Arceus (Wasser)" } ================================================ FILE: l10n/pokemon/fr-FR/gen1.json ================================================ { "bulbasaur": "Bulbizarre", "ivysaur": "Herbizarre", "venusaur": "Florizarre", "venusaur_female": "Florizarre (Femelle)", "charmander": "Salamèche", "charmeleon": "Reptincel", "charizard": "Dracaufeu", "squirtle": "Carapuce", "wartortle": "Carabaffe", "blastoise": "Tortank", "caterpie": "Chenipan", "metapod": "Chrysacier", "butterfree": "Papilusion", "weedle": "Aspicot", "kakuna": "Coconfort", "beedrill": "Dardargnan", "pidgey": "Roucool", "pidgeotto": "Roucoups", "pidgeot": "Roucarnage", "rattata": "Rattata", "raticate": "Rattatac", "spearow": "Piafabec", "fearow": "Rapasdepic", "ekans": "Abo", "arbok": "Arbok", "pikachu": "Pikachu", "pikachu_female": "Pikachu (Femelle)", "raichu": "Raichu", "sandshrew": "Sabelette", "sandslash": "Sablaireau", "nidoran_female": "Nidoran♀", "nidorina": "Nidorina", "nidoqueen": "Nidoqueen", "nidoran_male": "Nidoran♂", "nidorino": "Nidorino", "nidoking": "Nidoking", "clefairy": "Mélofée", "clefable": "Mélodelfe", "vulpix": "Goupix", "ninetales": "Feunard", "jigglypuff": "Rondoudou", "wigglytuff": "Grodoudou", "zubat": "Nosferapti", "golbat": "Nosferalto", "oddish": "Mystherbe", "gloom": "Ortide", "vileplume": "Rafflesia", "paras": "Paras", "parasect": "Parasect", "venonat": "Mimitoss", "venomoth": "Aéromite", "diglett": "Taupiqueur", "dugtrio": "Triopikeur", "meowth": "Miaouss", "persian": "Persian", "psyduck": "Psykokwak", "golduck": "Akwakwak", "mankey": "Férosinge", "primeape": "Colossinge", "growlithe": "Caninos", "arcanine": "Arcanin", "poliwag": "Ptitard", "poliwhirl": "Têtarte", "poliwrath": "Tartard", "abra": "Abra", "kadabra": "Kadabra", "alakazam": "Alakazam", "machop": "Machoc", "machoke": "Machopeur", "machamp": "Mackogneur", "bellsprout": "Chétiflor", "weepinbell": "Boustiflor", "victreebel": "Empiflor", "tentacool": "Tentacool", "tentacruel": "Tentacruel", "geodude": "Racaillou", "graveler": "Gravalanch", "golem": "Grolem", "ponyta": "Ponyta", "rapidash": "Galopa", "slowpoke": "Ramoloss", "slowbro": "Flagadoss", "magnemite": "Magnéti", "magneton": "Magnéton", "farfetchd": "Canarticho", "doduo": "Doduo", "dodrio": "Dodrio", "seel": "Otaria", "dewgong": "Lamantine", "grimer": "Tadmorv", "muk": "Grotadmorv", "shellder": "Kokiyas", "cloyster": "Crustabri", "gastly": "Fantominus", "haunter": "Spectrum", "gengar": "Ectoplasma", "onix": "Onix", "drowzee": "Soporifik", "hypno": "Hypnomade", "krabby": "Krabby", "kingler": "Krabboss", "voltorb": "Voltorbe", "electrode": "Électrode", "exeggcute": "Noeunoeuf", "exeggutor": "Noadkoko", "cubone": "Osselait", "marowak": "Ossatueur", "hitmonlee": "Kicklee", "hitmonchan": "Tygnon", "lickitung": "Excelangue", "koffing": "Smogo", "weezing": "Smogogo", "rhyhorn": "Rhinocorne", "rhydon": "Rhinoféros", "chansey": "Leveinard", "tangela": "Saquedeneu", "kangaskhan": "Kangourex", "horsea": "Hypotrempe", "seadra": "Hypocéan", "goldeen": "Poissirène", "seaking": "Poissoroy", "staryu": "Stari", "starmie": "Staross", "mrmime": "M. Mime", "scyther": "Insécateur", "jynx": "Lippoutou", "electabuzz": "Élektek", "magmar": "Magmar", "pinsir": "Scarabrute", "tauros": "Tauros", "magikarp": "Magicarpe", "gyarados": "Léviator", "lapras": "Lokhlass", "ditto": "Métamorph", "eevee": "Évoli", "vaporeon": "Aquali", "jolteon": "Voltali", "flareon": "Pyroli", "porygon": "Porygon", "omanyte": "Amonita", "omastar": "Amonistar", "kabuto": "Kabuto", "kabutops": "Kabutops", "aerodactyl": "Ptéra", "snorlax": "Ronflex", "articuno": "Artikodin", "zapdos": "Électhor", "moltres": "Sulfura", "dratini": "Minidraco", "dragonair": "Draco", "dragonite": "Dracolosse", "mewtwo": "Mewtwo", "mew": "Mew" } ================================================ FILE: l10n/pokemon/fr-FR/gen2.json ================================================ { "chikorita": "Germignon", "bayleef": "Macronium", "meganium": "Méganium", "meganium_female": "Méganium (Femelle)", "cyndaquil": "Héricendre", "quilava": "Feurisson", "typhlosion": "Typhlosion", "totodile": "Kaiminus", "croconaw": "Crocodil", "feraligatr": "Aligatueur", "sentret": "Fouinette", "furret": "Fouinar", "hoothoot": "Hoothoot", "noctowl": "Noarfang", "ledyba": "Coxy", "ledian": "Coxyclaque", "spinarak": "Mimigal", "ariados": "Migalos", "crobat": "Nostenfer", "chinchou": "Loupio", "lanturn": "Lanturn", "pichu": "Pichu", "cleffa": "Mélo", "igglybuff": "Toudoudou", "togepi": "Togepi", "togetic": "Togetic", "natu": "Natu", "xatu": "Xatu", "mareep": "Wattouat", "flaaffy": "Lainergie", "ampharos": "Pharamp", "bellossom": "Joliflor", "marill": "Marill", "azumarill": "Azumarill", "sudowoodo": "Simularbre", "politoed": "Tarpaud", "hoppip": "Granivol", "skiploom": "Floravol", "jumpluff": "Cotovol", "aipom": "Capumain", "sunkern": "Tournegrin", "sunflora": "Héliatronc", "yanma": "Yanma", "wooper": "Axoloto", "quagsire": "Maraiste", "espeon": "Mentali", "umbreon": "Noctali", "murkrow": "Cornèbre", "slowking": "Roigada", "misdreavus": "Feuforêve", "wobbuffet": "Qulbutoké", "wobbuffet_male": "Qulbutoké (Mâle)", "wobbuffet_female": "Qulbutoké (Femelle)", "girafarig": "Girafarig", "pineco": "Pomdepik", "forretress": "Foretress", "dunsparce": "Insolourdo", "gligar": "Scorplane", "steelix": "Steelix", "steelix_female": "Steelix (Femelle)", "snubbull": "Snubbull", "granbull": "Granbull", "qwilfish": "Qwilfish", "scizor": "Cizayox", "shuckle": "Caratroc", "heracross": "Scarhino", "heracross_male": "Scarhino (Mâle)", "heracross_female": "Scarhino (Femelle)", "sneasel": "Farfuret", "teddiursa": "Teddiursa", "ursaring": "Ursaring", "slugma": "Limagma", "magcargo": "Volcaropod", "swinub": "Marcacrin", "piloswine": "Cochignon", "corsola": "Corayon", "remoraid": "Rémoraid", "octillery": "Octillery", "delibird": "Cadoizo", "mantine": "Démanta", "skarmory": "Airmure", "houndour": "Malosse", "houndoom": "Démolosse", "kingdra": "Hyporoi", "phanpy": "Phanpy", "donphan": "Donphan", "porygon2": "Porygon2", "stantler": "Cerfrousse", "smeargle": "Queulorior", "tyrogue": "Debugant", "hitmontop": "Kapoera", "smoochum": "Lippouti", "elekid": "Élekid", "magby": "Magby", "miltank": "Écrémeuh", "blissey": "Leuphorie", "raikou": "Raikou", "entei": "Entei", "suicune": "Suicune", "larvitar": "Embrylex", "pupitar": "Ymphect", "tyranitar": "Tyranocif", "lugia": "Lugia", "hooh": "Ho-Oh", "celebi": "Celebi" } ================================================ FILE: l10n/pokemon/fr-FR/gen3.json ================================================ { "treecko": "Arcko", "grovyle": "Massko", "sceptile": "Jungko", "torchic": "Poussifeu", "combusken": "Galégon", "blaziken": "Braségali", "mudkip": "Gobou", "marshtomp": "Flobio", "swampert": "Laggron", "poochyena": "Medhyèna", "mightyena": "Grahyèna", "zigzagoon": "Zigzaton", "linoone": "Linéon", "wurmple": "Chenipotte", "silcoon": "Armulys", "beautifly": "Charmillon", "cascoon": "Blindalys", "dustox": "Papinox", "lotad": "Nénupiot", "lombre": "Lombre", "ludicolo": "Ludicolo", "seedot": "Grainipiot", "nuzleaf": "Pifeuil", "shiftry": "Tengalice", "taillow": "Nirondelle", "swellow": "Hélédelle", "wingull": "Goélise", "pelipper": "Bekipan", "ralts": "Tarsal", "kirlia": "Kirlia", "gardevoir": "Gardevoir", "surskit": "Arakdo", "masquerain": "Maskadra", "shroomish": "Balignon", "breloom": "Chapignon", "slakoth": "Parecool", "vigoroth": "Vigoroth", "slaking": "Monaflèmit", "nincada": "Ningale", "ninjask": "Ninjask", "shedinja": "Munja", "whismur": "Chuchmur", "loudred": "Ramboum", "exploud": "Brouhabam", "makuhita": "Makuhita", "hariyama": "Hariyama", "azurill": "Azurill", "nosepass": "Tarinor", "skitty": "Skitty", "delcatty": "Delcatty", "sableye": "Ténéfix", "mawile": "Mysdibule", "aron": "Galekid", "lairon": "Galegon", "aggron": "Galeking", "meditite": "Méditikka", "medicham": "Charmina", "electrike": "Dynavolt", "manectric": "Élecsprint", "plusle": "Posipi", "minun": "Négapi", "volbeat": "Muciole", "illumise": "Lumivole", "roselia": "Rosélia", "gulpin": "Gloupti", "swalot": "Avaltout", "carvanha": "Carvanha", "sharpedo": "Sharpedo", "wailmer": "Wailmer", "wailord": "Wailord", "numel": "Chamallot", "camerupt": "Camérupt", "torkoal": "Chartor", "spoink": "Spoink", "grumpig": "Groret", "spinda": "Spinda", "trapinch": "Kraknoix", "vibrava": "Vibraninf", "flygon": "Libégon", "cacnea": "Cacnea", "cacturne": "Cacturne", "swablu": "Tylton", "altaria": "Altaria", "zangoose": "Mangriff", "seviper": "Séviper", "lunatone": "Séléroc", "solrock": "Solaroc", "barboach": "Barloche", "whiscash": "Barbicha", "corpish": "Écrapince", "crawdaunt": "Colhomard", "baltoy": "Balbuto", "claydol": "Kaorine", "lileep": "Lilia", "cradily": "Vacilys", "anorith": "Anorith", "armaldo": "Armaldo", "feebas": "Barpau", "milotic": "Milobellus", "castform": "Morphéo", "kecleon": "Kecleon", "shuppet": "Polichombr", "banette": "Branette", "duskull": "Skelénox", "dusclops": "Téraclope", "tropius": "Tropius", "chimecho": "Éoko", "absol": "Absol", "wynaut": "Okéoké", "snorunt": "Stalgamin", "glalie": "Oniglali", "spheal": "Obalie", "sealeo": "Phogleur", "walrein": "Kaimorse", "clamperl": "Coquiperl", "huntail": "Serpang", "gorebyss": "Rosabyss", "relicanth": "Relicanth", "luvdisc": "Lovdisc", "bagon": "Draby", "shelgon": "Drackhaus", "salamence": "Drattak", "beldum": "Terhal", "metang": "Métang", "metagross": "Métalosse", "regirock": "Regirock", "regice": "Regice", "registeel": "Registeel", "latias": "Latias", "latios": "Latios", "kyogre": "Kyogre", "groudon": "Groudon", "rayquaza": "Rayquaza", "jirachi": "Jirachi", "deoxys": "Deoxys", "deoxys_speed": "Deoxys (Vitesse)", "deoxys_attack": "Deoxys (Attaque)", "deoxys_defense": "Deoxys (Défense)" } ================================================ FILE: l10n/pokemon/fr-FR/gen4.json ================================================ { "turtwig": "Tortipouss", "grotle": "Boskara", "torterra": "Torterra", "chimchar": "Ouisticram", "monferno": "Chimpenfeu", "infernape": "Simiabraz", "piplup": "Tiplouf", "prinplup": "Prinplouf", "empoleon": "Pingoléon", "starly": "Étourmi", "staravia": "Étourvol", "staraptor": "Étouraptor", "bidoof": "Keunotor", "bibarel": "Castorno", "kricketot": "Crikzik", "kricketune": "Mélokrik", "shinx": "Lixy", "luxio": "Luxio", "luxray": "Luxray", "budew": "Rozbouton", "roserade": "Roserade", "cranidos": "Kranidos", "rampardos": "Charkos", "shieldon": "Dinoclier", "bastiodon": "Bastiodon", "burmy_plant": "Cheniti (Plante)", "burmy_sandy": "Cheniti (Sable)", "burmy_trash": "Cheniti (Déchet)", "wormadam_plant": "Cheniselle (Plante)", "wormadam_sandy": "Cheniselle (Sable)", "wormadam_trash": "Cheniselle (Déchet)", "mothim": "Papilord", "combee_male": "Apitrini (Mâle)", "combee_female": "Apitrini (Femelle)", "vespiquen": "Apireine", "pachirisu": "Pachirisu", "buizel": "Mustébouée", "floatzel": "Mustéflott", "cherubi": "Ceribou", "cherrim": "Ceriflor", "shellos_west": "Sancoki (Ouest)", "shellos_east": "Sancoki (Est)", "gastrodon_west": "Tritosor (Ouest)", "gastrodon_east": "Tritosor (Est)", "ambipom": "Capidextre", "drifloon": "Baudrive", "drifblim": "Grodrive", "buneary": "Laporeille", "lopunny": "Lockpin", "mismagius": "Magirêve", "honchkrow": "Corboss", "glameow": "Chaglam", "purugly": "Chaffreux", "chingling": "Korillon", "stunky": "Moufouette", "skuntank": "Moufflair", "bronzor": "Archéomire", "bronzong": "Archéodong", "bonsly": "Manzaï", "mrmime": "M. Mime", "happiny": "Ptiravi", "chatot": "Pijako", "spiritomb": "Spiritomb", "gible": "Griknot", "gible_female": "Griknot (Femelle)", "gabite": "Carmache", "gabite_female": "Carmache (Femelle)", "garchomp": "Carchacrok", "garchomp_female": "Carchacrok (Femelle)", "munchlax": "Goinfrex", "riolu": "Riolu", "lucario": "Lucario", "hippopotas_male": "Hippopotas (Mâle)", "hippopotas_female": "Hippopotas (Femelle)", "hippowdon_male": "Hippodocus (Mâle)", "hippowdon_female": "Hippodocus (Femelle)", "skorupi": "Rapion", "drapion": "Drascore", "croagunk": "Cradopaud", "toxicroak": "Coatox", "carnivine": "Vortente", "finneon": "Écayon", "lumineon": "Luminéon", "mantyke": "Babimanta", "snover": "Blizzi", "abomasnow": "Blizzaroi", "weavile": "Dimoret", "magnezone": "Magnézone", "lickilicky": "Coudlangue", "rhyperior": "Rhinastoc", "tangrowth": "Bouldeneu", "electivire": "Élekable", "magmortar": "Maganon", "togekiss": "Togekiss", "yanmega": "Yanmega", "leafeon": "Phyllali", "glaceon": "Givrali", "gliscor": "Scorvol", "mamoswine": "Mammochon", "porygon_z": "Porygon-Z", "gallade": "Gallame", "probopass": "Tarinorme", "dusknoir": "Noctunoir", "froslass": "Momartik", "rotom": "Motisma", "rotom_heat": "Motisma (Chaleur)", "rotom_wash": "Motisma (Lavage)", "rotom_frost": "Motisma (Froid)", "rotom_fan": "Motisma (Hélice)", "rotom_mow": "Motisma (Tonte)", "uxie": "Créhelf", "mesprit": "Créfollet", "azelf": "Créfadet", "dialga": "Dialga", "palkia": "Palkia", "heatran": "Heatran", "regigigas": "Regigigas", "giratina": "Giratina", "giratina_origin": "Giratina (Origine)", "cresselia": "Cresselia", "phione": "Phione", "manaphy": "Manaphy", "darkrai": "Darkrai", "shaymin": "Shaymin", "shaymin_sky": "Shaymin (Ciel)", "arceus": "Arceus", "arceus_bug": "Arceus (Insecte)", "arceus_dark": "Arceus (Ténèbres)", "arceus_dragon": "Arceus (Dragon)", "arceus_electric": "Arceus (Électrik)", "arceus_fighting": "Arceus (Combat)", "arceus_fire": "Arceus (Feu)", "arceus_flying": "Arceus (Vol)", "arceus_ghost": "Arceus (Spectre)", "arceus_grass": "Arceus (Plante)", "arceus_ground": "Arceus (Sol)", "arceus_ice": "Arceus (Glace)", "arceus_poison": "Arceus (Poison)", "arceus_psychic": "Arceus (Psy)", "arceus_rock": "Arceus (Roche)", "arceus_steel": "Arceus (Acier)", "arceus_water": "Arceus (Eau)" } ================================================ FILE: l10n/pokemon/ja-JP/gen1.json ================================================ { "abra": "ケーシィ", "aerodactyl": "プテラ", "alakazam": "フーディン", "arbok": "アーボック", "arcanine": "ウインディ", "articuno": "フリーザー", "beedrill": "スピアー", "bellsprout": "マダツボミ", "blastoise": "カメックス", "bulbasaur": "フシギダネ", "butterfree": "バタフリー", "caterpie": "キャタピー", "chansey": "ラッキー", "charizard": "リザードン", "charmander": "ヒトカゲ", "charmeleon": "リザード", "clefable": "ピクシー", "clefairy": "ピッピ", "cloyster": "パルシェン", "cubone": "カラカラ", "dewgong": "ジュゴン", "diglett": "ディグダ", "ditto": "メタモン", "dodrio": "ドードリオ", "doduo": "ドードー", "dragonair": "ハクリュー", "dragonite": "カイリュー", "dratini": "ミニリュウ", "drowzee": "スリープ", "dugtrio": "ダグトリオ", "eevee": "イーブイ", "ekans": "アーボ", "electabuzz": "エレブー", "electrode": "マルマイン", "exeggcute": "タマタマ", "exeggutor": "ナッシー", "farfetchd": "カモネギ", "fearow": "オニドリル", "flareon": "ブースター", "gastly": "ゴース", "gengar": "ゲンガー", "geodude": "イシツブテ", "gloom": "クサイハナ", "golbat": "ゴルバット", "goldeen": "トサキント", "golduck": "ゴルダック", "golem": "ゴローニャ", "graveler": "ゴローン", "grimer": "ベトベター", "growlithe": "ガーディ", "gyarados": "ギャラドス", "haunter": "ゴースト", "hitmonchan": "エビワラー", "hitmonlee": "サワムラー", "horsea": "タッツー", "hypno": "スリーパー", "ivysaur": "フシギソウ", "jigglypuff": "プリン", "jolteon": "サンダース", "jynx": "ルージュラ", "kabuto": "カブト", "kabutops": "カブトプス", "kadabra": "ユンゲラー", "kakuna": "コクーン", "kangaskhan": "ガルーラ", "kingler": "キングラー", "koffing": "ドガース", "krabby": "クラブ", "lapras": "ラプラス", "lickitung": "ベロリンガ", "machamp": "カイリキー", "machoke": "ゴーリキー", "machop": "ワンリキー", "magikarp": "コイキング", "magmar": "ブーバー", "magnemite": "コイル", "magneton": "レアコイル", "mankey": "マンキー", "marowak": "ガラガラ", "meowth": "ニャース", "metapod": "トランセル", "mew": "ミュウ", "mewtwo": "ミュウツー", "moltres": "ファイヤー", "mrmime": "バリヤード", "muk": "ベトベトン", "nidoking": "ニドキング", "nidoqueen": "ニドクイン", "nidoran_female": "ニドラン♀", "nidoran_male": "ニドラン♂", "nidorina": "ニドリーナ", "nidorino": "ニドリーノ", "ninetales": "キュウコン", "oddish": "ナゾノクサ", "omanyte": "オムナイト", "omastar": "オムスター", "onix": "イワーク", "paras": "パラス", "parasect": "パラセクト", "persian": "ペルシアン", "pidgeot": "ピジョット", "pidgeotto": "ピジョン", "pidgey": "ポッポ", "pikachu": "ピカチュウ", "pikachu_female": "ピカチュウ(メス)", "pinsir": "カイロス", "poliwag": "ニョロモ", "poliwhirl": "ニョロゾ", "poliwrath": "ニョロボン", "ponyta": "ポニータ", "porygon": "ポリゴン", "primeape": "オコリザル", "psyduck": "コダック", "raichu": "ライチュウ", "rapidash": "ギャロップ", "raticate": "ラッタ", "rattata": "コラッタ", "rhydon": "サイドン", "rhyhorn": "サイホーン", "sandshrew": "サンド", "sandslash": "サンドパン", "scyther": "ストライク", "seadra": "シードラ", "seaking": "アズマオウ", "seel": "パウワウ", "shellder": "シェルダー", "slowbro": "ヤドラン", "slowpoke": "ヤドン", "snorlax": "カビゴン", "spearow": "オニスズメ", "squirtle": "ゼニガメ", "starmie": "スターミー", "staryu": "ヒトデマン", "tangela": "モンジャラ", "tauros": "ケンタロス", "tentacool": "メノクラゲ", "tentacruel": "ドククラゲ", "vaporeon": "シャワーズ", "venomoth": "モルフォン", "venonat": "コンパン", "venusaur": "フシギバナ", "venusaur_female": "フシギバナ(メス)", "victreebel": "ウツボット", "vileplume": "ラフレシア", "voltorb": "ビリリダマ", "vulpix": "ロコン", "wartortle": "カメール", "weedle": "ビードル", "weepinbell": "ウツドン", "weezing": "マタドガス", "wigglytuff": "プクリン", "zapdos": "サンダー", "zubat": "ズバット" } ================================================ FILE: l10n/pokemon/ja-JP/gen2.json ================================================ { "aipom": "エイパム", "ampharos": "デンリュウ", "ariados": "アリアドス", "azumarill": "マリルリ", "bayleef": "ベイリーフ", "bellossom": "キレイハナ", "blissey": "ハピナス", "celebi": "セレビィ", "chikorita": "チコリータ", "chinchou": "チョンチー", "cleffa": "ピィ", "corsola": "サニーゴ", "crobat": "クロバット", "croconaw": "アリゲイツ", "cyndaquil": "ヒノアラシ", "delibird": "デリバード", "donphan": "ドンファン", "dunsparce": "ノコッチ", "elekid": "エレキッド", "entei": "エンテイ", "espeon": "エーフィ", "feraligatr": "オーダイル", "flaaffy": "モココ", "forretress": "フォレトス", "furret": "オオタチ", "girafarig": "キリンリキ", "gligar": "グライガー", "granbull": "グランブル", "heracross": "ヘラクロス", "heracross_male": "ヘラクロス(オス)", "heracross_female": "ヘラクロス(メス)", "hitmontop": "カポエラー", "hooh": "ホウオウ", "hoothoot": "ホーホー", "hoppip": "ハネッコ", "houndoom": "ヘルガー", "houndour": "デルビル", "igglybuff": "ププリン", "jumpluff": "ワタッコ", "kingdra": "キングドラ", "lanturn": "ランターン", "larvitar": "ヨーギラス", "ledian": "レディアン", "ledyba": "レディバ", "lugia": "ルギア", "magby": "ブビィ", "magcargo": "マグカルゴ", "mantine": "マンタイン", "mareep": "メリープ", "marill": "マリル", "meganium": "メガニウム", "meganium_female": "メガニウム(メス)", "miltank": "ミルタンク", "misdreavus": "ムウマ", "murkrow": "ヤミカラス", "natu": "ネイティ", "noctowl": "ヨルノズク", "octillery": "オクタン", "phanpy": "ゴマゾウ", "pichu": "ピチュー", "piloswine": "イノムー", "pineco": "クヌギダマ", "politoed": "ニョロトノ", "porygon2": "ポリゴン2", "pupitar": "サナギラス", "quagsire": "ヌオー", "quilava": "マグマラシ", "qwilfish": "ハリーセン", "raikou": "ライコウ", "remoraid": "テッポウオ", "scizor": "ハッサム", "sentret": "オタチ", "shuckle": "ツボツボ", "skarmory": "エアームド", "skiploom": "ポポッコ", "slowking": "ヤドキング", "slugma": "マグマッグ", "smeargle": "ドーブル", "smoochum": "ムチュール", "sneasel": "ニューラ", "snubbull": "ブルー", "spinarak": "イトマル", "stantler": "オドシシ", "steelix": "ハガネール", "steelix_female": "ハガネール(メス)", "sudowoodo": "ウソッキー", "suicune": "スイクン", "sunflora": "キマワリ", "sunkern": "ヒマナッツ", "swinub": "ウリムー", "teddiursa": "ヒメグマ", "togepi": "トゲピー", "togetic": "トゲチック", "totodile": "ワニノコ", "typhlosion": "バクフーン", "tyranitar": "バンギラス", "tyrogue": "バルキー", "umbreon": "ブラッキー", "ursaring": "リングマ", "wobbuffet": "ソーナノ", "wobbuffet_male": "ソーナノ(オス)", "wobbuffet_female": "ソーナノ(メス)", "wooper": "ウパー", "xatu": "ネイティオ", "yanma": "ヤンヤンマ" } ================================================ FILE: l10n/pokemon/ja-JP/gen3.json ================================================ { "absol": "アブソル", "aggron": "ボスゴドラ", "altaria": "チルタリス", "anorith": "アノプス", "armaldo": "アーマルド", "aron": "ココドラ", "azurill": "ルリリ", "bagon": "タツベイ", "baltoy": "ヤジロン", "banette": "ジュペッタ", "barboach": "ドジョッチ", "beautifly": "アゲハント", "beldum": "ダンバル", "blaziken": "バシャーモ", "breloom": "キノガッサ", "cacnea": "サボネア", "cacturne": "ノクタス", "camerupt": "バクーダ", "carvanha": "キバニア", "cascoon": "マユルド", "castform": "ポワルン", "chimecho": "チリーン", "clamperl": "パールル", "claydol": "ネンドール", "combusken": "ワカシャモ", "corpish": "ヘイガニ", "cradily": "ユレイドル", "crawdaunt": "シザリガー", "delcatty": "エネコロロ", "deoxys": "デオキシス", "deoxys_attack": "デオキシス(攻撃)", "deoxys_defense": "デオキシス(防御)", "deoxys_speed": "デオキシス(速度)", "dusclops": "サマヨール", "duskull": "ヨマワル", "dustox": "ドクケイル", "electrike": "ラクライ", "exploud": "バクオング", "feebas": "ヒンバス", "flygon": "フライゴン", "gardevoir": "サーナイト", "glalie": "オニゴーリ", "gorebyss": "サクラビス", "groudon": "グラードン", "grovyle": "ジュプトル", "grumpig": "ブーピッグ", "gulpin": "ゴクリン", "hariyama": "ハリテヤマ", "huntail": "ハンテール", "illumise": "イルミーゼ", "jirachi": "ジラーチ", "kecleon": "カクレオン", "kirlia": "キルリア", "kyogre": "カイオーガ", "lairon": "コドラ", "latias": "ラティアス", "latios": "ラティオス", "lileep": "リリーラ", "linoone": "マッスグマ", "lombre": "ハスブレロ", "lotad": "ハスボー", "loudred": "ドゴーム", "ludicolo": "ルンパッパ", "lunatone": "ルナトーン", "luvdisc": "ラブカス", "makuhita": "マクノシタ", "manectric": "ライボルト", "marshtomp": "ヌマクロー", "masquerain": "アメモース", "mawile": "クチート", "medicham": "チャーレム", "meditite": "アサナン", "metagross": "メタグロス", "metang": "メタング", "mightyena": "グラエナ", "milotic": "ミロカロス", "minun": "マイナン", "mudkip": "ミズゴロウ", "nincada": "ツチニン", "ninjask": "テッカニン", "nosepass": "ノズパス", "numel": "ドンメル", "nuzleaf": "コノハナ", "pelipper": "ペリッパー", "plusle": "プラスル", "poochyena": "ポチエナ", "ralts": "ラルトス", "rayquaza": "レックウザ", "regice": "レジアイス", "regirock": "レジロック", "registeel": "レジスチル", "relicanth": "ジーランス", "roselia": "ロゼリア", "sableye": "ヤミラミ", "salamence": "ボーマンダ", "sceptile": "ジュカイン", "sealeo": "トドグラー", "seedot": "タネボー", "seviper": "ハブネーク", "sharpedo": "サメハダー", "shedinja": "ヌケニン", "shelgon": "コモルー", "shiftry": "ダーテング", "shroomish": "キノココ", "shuppet": "カゲボウズ", "silcoon": "カラサリス", "skitty": "エネコ", "slaking": "ケッキング", "slakoth": "ナマケロ", "snorunt": "ユキワラシ", "solrock": "ソルロック", "spheal": "タマザラシ", "spinda": "パッチール", "spoink": "バネブー", "surskit": "アメタマ", "swablu": "チルット", "swalot": "マルノーム", "swampert": "ラグラージ", "swellow": "オオスバメ", "taillow": "スバメ", "torchic": "アチャモ", "torkoal": "コータス", "trapinch": "ナックラー", "treecko": "キモリ", "tropius": "トロピウス", "vibrava": "ビブラーバ", "vigoroth": "ヤルキモノ", "volbeat": "バルビート", "wailmer": "ホエルコ", "wailord": "ホエルオー", "walrein": "トドゼルガ", "whiscash": "ナマズン", "whismur": "ゴニョニョ", "wingull": "キャモメ", "wurmple": "ケムッソ", "wynaut": "ソーナノ", "zangoose": "ザングース", "zigzagoon": "ジグザグマ" } ================================================ FILE: l10n/pokemon/ja-JP/gen4.json ================================================ { "turtwig": "ナエトル", "grotle": "ハヤシガメ", "torterra": "ドダイトス", "chimchar": "ヒコザル", "monferno": "モウカザル", "infernape": "ゴウカザル", "piplup": "ポッチャマ", "prinplup": "ポッタイシ", "empoleon": "エンペルト", "starly": "ムックル", "staravia": "ムクバード", "staraptor": "ムクホーク", "bidoof": "ビッパ", "bibarel": "ビーダル", "kricketot": "コロボーシ", "kricketune": "コロトック", "shinx": "コリンク", "luxio": "ルクシオ", "luxray": "レントラー", "budew": "スボミー", "roserade": "ロズレイド", "cranidos": "ズガイドス", "rampardos": "ラムパルド", "shieldon": "タテトプス", "bastiodon": "トリデプス", "burmy_plant": "ミノムッチ(くさきのミノ)", "burmy_sandy": "ミノムッチ(すなちのミノ)", "burmy_trash": "ミノムッチ(ゴミのミノ)", "wormadam_plant": "ミノマダム(くさきのミノ)", "wormadam_sandy": "ミノマダム(すなちのミノ)", "wormadam_trash": "ミノマダム(ゴミのミノ)", "mothim": "ガーメイル", "combee_male": "ミツハニー(オス)", "combee_female": "ミツハニー(メス)", "vespiquen": "ビークイン", "pachirisu": "パチリス", "buizel": "ブイゼル", "floatzel": "フローゼル", "cherubi": "チェリンボ", "cherrim": "チェリム", "shellos_west": "カラナクシ(にしのうみ)", "shellos_east": "カラナクシ(ひがしのうみ)", "gastrodon_west": "トリトドン(にしのうみ)", "gastrodon_east": "トリトドン(ひがしのうみ)", "ambipom": "エテボース", "drifloon": "フワンテ", "drifblim": "フワライド", "buneary": "ミミロル", "lopunny": "ミミロップ", "mismagius": "ムウマージ", "honchkrow": "ドンカラス", "glameow": "ニャルマー", "purugly": "ブニャット", "chingling": "リーシャン", "stunky": "スカンプー", "skuntank": "スカタンク", "bronzor": "ドーミラー", "bronzong": "ドータクン", "bonsly": "ウソハチ", "mrmime": "バリヤード", "happiny": "ピンプク", "chatot": "ペラップ", "spiritomb": "ミカルゲ", "gible": "フカマル", "gible_female": "フカマル(メス)", "gabite": "ガバイト", "gabite_female": "ガバイト(メス)", "garchomp": "ガブリアス", "garchomp_female": "ガブリアス(メス)", "munchlax": "ゴンベ", "riolu": "リオル", "lucario": "ルカリオ", "hippopotas_male": "ヒポポタス(オス)", "hippopotas_female": "ヒポポタス(メス)", "hippowdon_male": "カバルドン(オス)", "hippowdon_female": "カバルドン(メス)", "skorupi": "スコルピ", "drapion": "ドラピオン", "croagunk": "グレッグル", "toxicroak": "ドクロッグ", "carnivine": "マスキッパ", "finneon": "ケイコウオ", "lumineon": "ネオラント", "mantyke": "タマンタ", "snover": "ユキカブリ", "abomasnow": "ユキノオー", "weavile": "マニューラ", "magnezone": "ジバコイル", "lickilicky": "ベロベルト", "rhyperior": "ドサイドン", "tangrowth": "モジャンボ", "electivire": "エレキブル", "magmortar": "ブーバーン", "togekiss": "トゲキッス", "yanmega": "メガヤンマ", "leafeon": "リーフィア", "glaceon": "グレイシア", "gliscor": "グライオン", "mamoswine": "マンムー", "porygon_z": "ポリゴンZ", "gallade": "エルレイド", "probopass": "ダイノーズ", "dusknoir": "ヨノワール", "froslass": "ユキメノコ", "rotom": "ロトム", "rotom_heat": "ロトム(ヒート)", "rotom_wash": "ロトム(ウォッシュ)", "rotom_frost": "ロトム(フロスト)", "rotom_fan": "ロトム(スピン)", "rotom_mow": "ロトム(カット)", "uxie": "ユクシー", "mesprit": "エムリット", "azelf": "アグノム", "dialga": "ディアルガ", "palkia": "パルキア", "heatran": "ヒードラン", "regigigas": "レジギガス", "giratina": "ギラティナ", "giratina_origin": "ギラティナ(オリジンフォルム)", "cresselia": "クレセリア", "phione": "フィオネ", "manaphy": "マナフィ", "darkrai": "ダークライ", "shaymin": "シェイミ", "shaymin_sky": "シェイミ(スカイフォルム)", "arceus": "アルセウス", "arceus_bug": "アルセウス(むし)", "arceus_dark": "アルセウス(あく)", "arceus_dragon": "アルセウス(ドラゴン)", "arceus_electric": "アルセウス(でんき)", "arceus_fighting": "アルセウス(かくとう)", "arceus_fire": "アルセウス(ほのお)", "arceus_flying": "アルセウス(ひこう)", "arceus_ghost": "アルセウス(ゴースト)", "arceus_grass": "アルセウス(くさ)", "arceus_ground": "アルセウス(じめん)", "arceus_ice": "アルセウス(こおり)", "arceus_poison": "アルセウス(どく)", "arceus_psychic": "アルセウス(エスパー)", "arceus_rock": "アルセウス(いわ)", "arceus_steel": "アルセウス(はがね)", "arceus_water": "アルセウス(みず)" } ================================================ FILE: media/.gitignore ================================================ unused/ ================================================ FILE: media/pokemon.css ================================================ :root { --container-paddding: 20px; --input-padding-vertical: 6px; --input-padding-horizontal: 4px; --input-margin-vertical: 4px; --input-margin-horizontal: 0; } * { user-select: none; } body { padding: 0 var(--container-paddding); color: var(--vscode-foreground); font-size: var(--vscode-font-size); font-weight: var(--vscode-font-weight); font-family: var(--vscode-font-family); background-color: var(--vscode-editor-background); background-attachment: fixed; background-repeat: repeat-x; background-position: bottom left; overflow: hidden; /* Hide scrollbars */ } #foreground { width: 100%; height: 100%; position: absolute; top: 0; left: 0; z-index: 5; background-attachment: fixed; background-repeat: repeat-x; background-position: bottom left; } ol, ul { padding-left: var(--container-paddding); } body>*, form>* { margin-block-start: var(--input-margin-vertical); margin-block-end: var(--input-margin-vertical); } *:focus { outline-color: var(--vscode-focusBorder) !important; } a { color: var(--vscode-textLink-foreground); } a:hover, a:active { color: var(--vscode-textLink-activeForeground); } code { font-size: var(--vscode-editor-font-size); font-family: var(--vscode-editor-font-family); } button { border: none; padding: var(--input-padding-vertical) var(--input-padding-horizontal); width: 100%; text-align: center; outline: 1px solid transparent; outline-offset: 2px !important; color: var(--vscode-button-foreground); background: var(--vscode-button-background); } button:hover { cursor: pointer; background: var(--vscode-button-hoverBackground); } button:focus { outline-color: var(--vscode-focusBorder); } button.secondary { color: var(--vscode-button-secondaryForeground); background: var(--vscode-button-secondaryBackground); } button.secondary:hover { background: var(--vscode-button-secondaryHoverBackground); } input:not([type='checkbox']), textarea { display: block; width: 100%; border: none; font-family: var(--vscode-font-family); padding: var(--input-padding-vertical) var(--input-padding-horizontal); color: var(--vscode-input-foreground); outline-color: var(--vscode-input-border); background-color: var(--vscode-input-background); } input::placeholder, textarea::placeholder { color: var(--vscode-input-placeholderForeground); } #pokemonCanvas { position: fixed; bottom: 0; left: 0; z-index: 3; } img.pokemon { -webkit-transform: scaleX(-1); transform: scaleX(-1); position: absolute; image-rendering: pixelated; left: 0px; right: 0px; bottom: 0px; z-index: 2; } .collision { position: absolute; left: 0px; right: 0px; bottom: 0px; z-index: 999; } .bubble { image-rendering: pixelated; position: absolute; text-align: center; margin: auto; opacity: 0; animation: fadeIn 0.2s forwards; } @keyframes fadeIn { 0% { opacity: 0; transform: translateX(50%) translateY(10px); } 100% { opacity: 1; transform: translateX(50%) translateY(0); } } .bubble-nano { width: 15px; } .bubble-small { width: 22.5px; } .bubble-medium { width: 30px; } .bubble-large { width: 37.5px; } /* Manually adjust the size teh bubble on 64x64px pokemon. Quick fix for now, TODO */ .bubble-nano.b-64 { margin-left: 15px; } .bubble-small.b-64 { margin-left: 22.5px; } .bubble-medium.b-64 { margin-left: 30px; } .bubble-large.b-64 { margin-left: 37.5px; } .pokeball-sprite { --frame-size: 64px; --frames: 6; position: absolute; width: var(--frame-size); height: var(--frame-size); background-image: url('pokeball_sprite_sheet.png'); background-repeat: no-repeat; background-position: 0 0; background-size: var(--frame-size) calc(var(--frame-size) * var(--frames)); image-rendering: pixelated; z-index: 0; } .pokeball-sprite.pokeball-open { animation: pokeball-open 0.45s steps(var(--frames)) forwards; } @keyframes pokeball-open { to { background-position-y: calc(-1 * var(--frame-size) * (var(--frames))); } } .pokeball-sprite.pokeball-close { animation: pokeball-close 0.6s steps(var(--frames)) backwards; } @keyframes pokeball-close { from { background-position-y: calc(-1 * var(--frame-size) * (var(--frames)));} to { background-position-y: 0; } } .pokemon.spawn-pop { animation: pokemon-pop 150ms ease-out; opacity: 1 !important; will-change: transform, opacity, filter; } @keyframes pokemon-pop { 0% { transform: scale(0.4); opacity: 0; filter: saturate(0) brightness(3) contrast(1); } 40% { filter: saturate(0.3) brightness(1.8) contrast(1.05); } 60% { transform: scale(1.15); opacity: 1; filter: saturate(0.8) brightness(1.1) contrast(1); } 100% { transform: scale(1); opacity: 1; filter: none; } } .shiny-overlay { position: absolute; image-rendering: pixelated; z-index: 9999; pointer-events: none; mix-blend-mode: screen; margin-bottom: -5px; animation: shiny-sparkle 1s ease-out forwards; } @keyframes shiny-sparkle { 0% { opacity: 0; transform: scale(0.5); } 15% { opacity: 1; transform: scale(1.2); } 30% { transform: scale(1); } 80% { opacity: 1; } 100% { opacity: 0; } } .pokemon.fade-out { animation: pokemon-fade-out 220ms ease-out; } @keyframes pokemon-fade-out { 0% { opacity: 1; filter: none; } 40% { transform: scale(1.15); filter: saturate(0.8) brightness(1.1) contrast(1); } 60% { opacity: 0.4; filter: saturate(0.3) brightness(1.8) contrast(1.05); } 100% { transform: scale(0.4); opacity: 0; filter: saturate(0) brightness(3) contrast(1); } } ================================================ FILE: media/reset.css ================================================ html { box-sizing: border-box; font-size: 13px; } *, *:before, *:after { box-sizing: inherit; } body, h1, h2, h3, h4, h5, h6, p, ol, ul { margin: 0; padding: 0; font-weight: normal; } img { max-width: 100%; height: auto; } ================================================ FILE: package.json ================================================ { "name": "vscode-pokemon", "displayName": "vscode-pokemon", "description": "Pokémon for your VS Code", "version": "4.3.5", "engines": { "vscode": "^1.73.0" }, "l10n": "./l10n", "repository": { "type": "github", "url": "https://github.com/jakobhoeg/vscode-pokemon" }, "homepage": "https://github.com/jakobhoeg/vscode-pokemon", "bugs": "https://github.com/jakobhoeg/vscode-pokemon/issues", "publisher": "jakobhoeg", "pricing": "Free", "categories": [ "Other" ], "keywords": [ "pokemon", "pets", "pokémon", "pixelart", "pixel", "pixel", "vscode" ], "license": "MIT", "icon": "icon.png", "activationEvents": [ "onCommand:vscode-pokemon.start", "onCommand:vscode-pokemon.spawn-pokemon", "onCommand:vscode-pokemon.spawn-random-pokemon", "onCommand:vscode-pokemon.delete-pokemon", "onCommand:vscode-pokemon.remove-all-pokemon", "onCommand:vscode-pokemon.roll-call", "onCommand:vscode-pokemon.export-pokemon-list", "onCommand:vscode-pokemon.import-pokemon-list", "onCommand:vscode-pokemon.configure-keybindings", "onCommand:vscode-pokemon.change-pokemon-language", "onWebviewPanel:pokemonCoding", "onView:explorer", "onView:pokemonView", "onStartupFinished" ], "main": "./out/extension/extension.js", "browser": "./dist/web/extension-web.js", "contributes": { "views": { "explorer": [ { "type": "webview", "id": "pokemonView", "name": "VS Code Pokémon", "when": "vscode-pokemon.position == 'explorer'", "icon": "media/icon/dark-add.svg" } ] }, "menus": { "view/title": [ { "command": "vscode-pokemon.spawn-pokemon", "when": "view == pokemonView", "group": "navigation@1" }, { "command": "vscode-pokemon.spawn-random-pokemon", "when": "view == pokemonView", "group": "navigation@2" }, { "command": "vscode-pokemon.delete-pokemon", "when": "view == pokemonView", "group": "navigation@3" } ] }, "commands": [ { "command": "vscode-pokemon.start", "title": "Start pokemon coding session", "category": "Pokemon Coding" }, { "command": "vscode-pokemon.export-pokemon-list", "title": "Export pokemon list", "category": "Pokemon Coding" }, { "command": "vscode-pokemon.import-pokemon-list", "title": "Import pokemon list", "category": "Pokemon Coding" }, { "command": "vscode-pokemon.spawn-pokemon", "title": "Spawn additional pokemon", "category": "Pokemon Coding", "icon": { "dark": "media/icon/dark-add.svg", "light": "media/icon/light-add.svg" } }, { "command": "vscode-pokemon.spawn-random-pokemon", "title": "Spawn random additional pokemon", "category": "Pokemon Coding", "icon": { "dark": "media/icon/dark-random.svg", "light": "media/icon/light-random.svg" } }, { "command": "vscode-pokemon.delete-pokemon", "title": "Remove pokemon", "category": "Pokemon Coding", "icon": { "dark": "media/icon/dark-trash.svg", "light": "media/icon/light-trash.svg" } }, { "command": "vscode-pokemon.remove-all-pokemon", "title": "Remove all pokemon", "category": "Pokemon Coding", "icon": { "dark": "media/icon/dark-trash.svg", "light": "media/icon/light-trash.svg" } }, { "command": "vscode-pokemon.roll-call", "title": "Roll-call", "category": "Pokemon Coding" }, { "command": "vscode-pokemon.configure-keybindings", "title": "Configure keybindings", "category": "Pokemon Coding" }, { "command": "vscode-pokemon.change-pokemon-language", "title": "Change Pokemon language", "category": "Pokemon Coding" } ], "keybindings": [ { "command": "vscode-pokemon.spawn-pokemon", "key": "alt+shift+w", "mac": "alt+shift+w" }, { "command": "vscode-pokemon.spawn-random-pokemon", "key": "alt+shift+q", "mac": "alt+shift+q" }, { "command": "vscode-pokemon.delete-pokemon", "key": "alt+shift+d", "mac": "alt+shift+d" }, { "command": "vscode-pokemon.remove-all-pokemon", "key": "alt+shift+backspace", "mac": "alt+shift+backspace" } ], "configuration": [ { "title": "VS Code Pokemon", "properties": { "vscode-pokemon.pokemonSize": { "type": "string", "enum": [ "nano", "small", "medium", "large" ], "default": "medium", "description": "Pokemon size" }, "vscode-pokemon.position": { "type": "string", "enum": [ "panel", "explorer" ], "default": "explorer", "description": "VSCode pokemon webview position" }, "vscode-pokemon.theme": { "type": "string", "enum": [ "none", "forest", "castle", "beach" ], "default": "none", "description": "Background theme assets for your pokemon" }, "vscode-pokemon.defaultPokemon": { "type": "array", "items": { "type": "object", "properties": { "type": { "type": "string", "description": "Pokemon type (e.g., 'pikachu', 'charizard', 'bulbasaur')" }, "name": { "type": "string", "description": "Custom name for the pokemon (optional)" } }, "required": [ "type" ] }, "default": [], "description": "List of default pokemon to automatically spawn on startup. Each pokemon should have a 'type' (required), and optionally 'name'. Example: [{\"type\": \"pikachu\", \"name\": \"Sparky\"}, {\"type\": \"charizard\"}]" }, "vscode-pokemon.shinyOdds": { "type": "number", "default": 8192, "minimum": 1, "description": "Odds (1 in N) for a Pokémon to be shiny. Lower = more shinies. Default is 8192." }, "vscode-pokemon.pokemonLanguage": { "type": "string", "enum": [ "auto", "en-US", "fr-FR", "de-DE", "ja-JP" ], "default": "auto", "description": "Language for Pokemon names. 'auto' uses VS Code's language, or you can choose a specific language (e.g., 'fr-FR' for French, 'en-US' for English, 'de-DE' for German, 'ja-JP' for Japanese). Only official Pokemon languages are supported." } } } ] }, "scripts": { "vscode:prepublish": "npm run compile", "compile:panel": "webpack", "compile:extension": "tsc -p ./tsconfig.extension.json", "compile:test": "tsc -p ./tsconfig.test.json", "compile:web": "webpack", "compile": "npm run compile:panel && npm run compile:extension && npm run compile:test && npm run compile:web", "watch": "webpack && tsc -watch -p ./tsconfig.extension.json", "watch:web": "webpack --watch", "pretest": "npm run compile && npm run lint", "lint": "eslint src --ext ts", "lint:fix": "eslint src --ext ts --fix", "format:check": "prettier --check src", "format": "prettier --write src", "test": "node ./out/test/runTest.js", "test:coverage": "COVERAGE=1 node ./out/test/runTest.js", "test:web": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. --extensionTestsPath=dist/web/test/suite/index.js", "test:gifs": "node ./out/test/gifs.js", "prepare": "husky" }, "devDependencies": { "@rbarilani/remove-source-map-url-webpack-plugin": "^1.1.0", "@types/glob": "^7.1.3", "@types/jsdom": "^20.0.0", "@types/mocha": "^9.1.1", "@types/node": "^18.0.0", "@types/vscode": "^1.73.0", "@typescript-eslint/eslint-plugin": "^5.29.0", "@typescript-eslint/parser": "^5.29.0", "@vscode/l10n-dev": "^0.0.29", "@vscode/test-web": "^0.0.50", "eslint": "^8.18.0", "eslint-config-prettier": "^9.1.2", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-unused-imports": "^2.0.0", "glob": "^8.0.3", "gulp": "^5.0.0", "husky": "^9.1.7", "jsdom": "^20.0.0", "jsdom-global": "^3.0.2", "mocha": "^10.0.0", "nyc": "^15.1.0", "path-browserify": "^1.0.1", "prettier": "^3.3.3", "process": "^0.11.10", "ts-loader": "^9.3.0", "typescript": "^4.7.4", "typescript-eslint": "^0.0.1-alpha.0", "vscode-test": "^1.4.0", "webpack": "5.95.0", "webpack-cli": "^4.10.0" }, "dependencies": { "@vscode/l10n": "^0.0.10" }, "lint-staged": { "*.ts": [ "eslint --fix", "prettier --write" ] } } ================================================ FILE: src/common/localize.ts ================================================ import * as fs from 'fs'; import * as path from 'path'; import * as vscode from 'vscode'; import { POKEMON_DATA } from './pokemon-data'; import { PokemonType } from './types'; /** * Cache for loaded Pokemon translations * Key: locale (e.g., 'fr-FR'), Value: translations map (pokemon key -> translated name) */ let pokemonTranslationsCache: { [locale: string]: { [key: string]: string } } = {}; /** * Supported Pokemon translation locales * These correspond to the folders in l10n/pokemon/ */ export const SUPPORTED_LOCALES = ['en-US', 'fr-FR', 'de-DE', 'ja-JP'] as const; export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number]; const GENERATIONS = ['gen1', 'gen2', 'gen3', 'gen4'] as const; const FALLBACK_LOCALE = 'en-US'; /** * Resets the Pokemon translations cache * Useful when the language configuration changes */ export function resetPokemonTranslationsCache(): void { pokemonTranslationsCache = {}; } /** * Gets the configured locale for Pokemon names * Uses vscode-pokemon.pokemonLanguage configuration if set, * otherwise falls back to VS Code's language * @returns The locale string (e.g., 'fr-FR', 'en-US') */ function getPokemonLocale(): string { const config = vscode.workspace.getConfiguration('vscode-pokemon'); const configuredLocale = config.get('pokemonLanguage', 'auto'); // If a specific language is configured and different from 'auto' if (configuredLocale && configuredLocale !== 'auto') { return configuredLocale.toLowerCase().replace(/_/g, '-'); } // Default: use VS Code's language return vscode.env.language.toLowerCase().replace(/_/g, '-'); } /** * Gets the extension path, with caching */ function getExtensionPath(): string | undefined { const extension = vscode.extensions.getExtension('jakobhoeg.vscode-pokemon'); return extension?.extensionPath; } /** * Resolves the path to Pokemon translation files for a given locale */ function resolvePokemonL10nPath(locale: string): string | undefined { const extensionPath = getExtensionPath(); const basePath = extensionPath ? path.join(extensionPath, 'l10n', 'pokemon') : path.join(__dirname, '../../l10n/pokemon'); const localePath = path.join(basePath, locale); if (fs.existsSync(localePath)) { return localePath; } // Fallback to en-US const fallbackPath = path.join(basePath, FALLBACK_LOCALE); return fs.existsSync(fallbackPath) ? fallbackPath : undefined; } /** * Loads Pokemon translations from generation files (gen1.json, gen2.json, gen3.json) * Translations are stored in l10n/pokemon/{locale}/gen*.json * * Note: English names are the default source of truth defined in * src/common/pokemon-generations/gen*.ts files. Translation files are optional * and missing translations will fall back to English names. * * @param locale The locale to load (e.g., 'fr-FR', 'en-US'). Uses configured locale if not provided * @returns Map of Pokemon keys to translated names */ function loadPokemonTranslations(locale?: string): { [key: string]: string } { // Use provided locale or get from configuration const targetLocale = locale || getPokemonLocale(); // Return cached translations if available if (pokemonTranslationsCache[targetLocale]) { return pokemonTranslationsCache[targetLocale]; } // Initialize cache for this locale const cache: { [key: string]: string } = {}; pokemonTranslationsCache[targetLocale] = cache; try { const pokemonL10nPath = resolvePokemonL10nPath(targetLocale); if (!pokemonL10nPath) { console.warn( `[Pokemon Translations] Directory not found for locale: ${targetLocale}`, ); return cache; } let totalLoaded = 0; for (const gen of GENERATIONS) { const genFile = path.join(pokemonL10nPath, `${gen}.json`); if (!fs.existsSync(genFile)) { continue; } try { const genData = JSON.parse(fs.readFileSync(genFile, 'utf8')); Object.assign(cache, genData); totalLoaded += Object.keys(genData).length; } catch (error) { console.warn(`[Pokemon Translations] Error loading ${genFile}:`, error); } } if (totalLoaded > 0) { console.log( `[Pokemon Translations] Loaded ${totalLoaded} translations from ${pokemonL10nPath}`, ); } else { console.warn( `[Pokemon Translations] No translations found in ${pokemonL10nPath}`, ); } } catch (error) { console.error('[Pokemon Translations] Error loading translations:', error); } return cache; } export class TranslatedQuickPickItem implements vscode.QuickPickItem { label: string; value: T; constructor(label: string, value: T) { this.label = label; this.value = value; } } export function stringListAsQuickPickItemList( collection: Array, ): TranslatedQuickPickItem[] { return collection.map>((el) => { return { label: vscode.l10n.t(String(el)), value: el }; }); } /** * Gets the localized name of a Pokemon. * Loads translations from l10n/pokemon/{locale}/gen*.json files. * Falls back to the English name from POKEMON_DATA if no translation is available. * * @param pokemonType The Pokemon type (e.g., 'pikachu', 'charizard') * @returns The localized Pokemon name, or English name if translation not found */ export function getLocalizedPokemonName(pokemonType: PokemonType): string { const translations = loadPokemonTranslations(); return ( translations[pokemonType] || POKEMON_DATA[pokemonType]?.name || pokemonType ); } ================================================ FILE: src/common/names.ts ================================================ import { POKEMON_NAMES } from '../panel/pokemon'; export function randomName(): string { const collection: ReadonlyArray = POKEMON_NAMES; return collection[Math.floor(Math.random() * collection.length)] ?? 'Unknown'; } ================================================ FILE: src/common/pokemon-data.ts ================================================ /* eslint-disable no-unused-vars */ /* eslint-disable @typescript-eslint/naming-convention */ import { PokemonColor, PokemonConfig, PokemonExtraSprite, PokemonGeneration, PokemonType, } from './types'; export const POKEMON_DATA: { [key: string]: PokemonConfig } = { // Generation 1 bulbasaur: { id: 1, name: 'Bulbasaur', generation: PokemonGeneration.Gen1, cry: 'Bulbasaur!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ivysaur: { id: 2, name: 'Ivysaur', generation: PokemonGeneration.Gen1, cry: 'Ivysaur!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, venusaur: { id: 3, name: 'Venusaur', generation: PokemonGeneration.Gen1, cry: 'Venusaur!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, venusaur_female: { id: 3, name: 'Venusaur (Female)', generation: PokemonGeneration.Gen1, cry: 'Venusaur!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, charmander: { id: 4, name: 'Charmander', generation: PokemonGeneration.Gen1, cry: 'Charmander!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, charmeleon: { id: 5, name: 'Charmeleon', generation: PokemonGeneration.Gen1, cry: 'Charmeleon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, charizard: { id: 6, name: 'Charizard', generation: PokemonGeneration.Gen1, cry: 'Charizard!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, squirtle: { id: 7, name: 'Squirtle', generation: PokemonGeneration.Gen1, cry: 'Squritle!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wartortle: { id: 8, name: 'Wartortle', generation: PokemonGeneration.Gen1, cry: 'Wartortle!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, blastoise: { id: 9, name: 'Blastoise', generation: PokemonGeneration.Gen1, cry: 'Blastoise!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, caterpie: { id: 10, name: 'Caterpie', generation: PokemonGeneration.Gen1, cry: 'Caterpie!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, metapod: { id: 11, name: 'Metapod', generation: PokemonGeneration.Gen1, cry: 'Metapod!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, butterfree: { id: 12, name: 'Butterfree', generation: PokemonGeneration.Gen1, cry: 'Butterfree!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, weedle: { id: 13, name: 'Weedle', generation: PokemonGeneration.Gen1, cry: 'Weedle!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kakuna: { id: 14, name: 'Kakuna', generation: PokemonGeneration.Gen1, cry: 'Kakuna!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, beedrill: { id: 15, name: 'Beedrill', generation: PokemonGeneration.Gen1, cry: 'Beedrill!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pidgey: { id: 16, name: 'Pidgey', generation: PokemonGeneration.Gen1, cry: 'Pidgey!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pidgeotto: { id: 17, name: 'Pidgeotto', generation: PokemonGeneration.Gen1, cry: 'Pidgeotto!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pidgeot: { id: 18, name: 'Pidgeot', generation: PokemonGeneration.Gen1, cry: 'Pidgeot!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rattata: { id: 19, name: 'Rattata', generation: PokemonGeneration.Gen1, cry: 'Rattata!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, raticate: { id: 20, name: 'Raticate', generation: PokemonGeneration.Gen1, cry: 'Raticate!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, spearow: { id: 21, name: 'Spearow', generation: PokemonGeneration.Gen1, cry: 'Spearow!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, fearow: { id: 22, name: 'Fearow', generation: PokemonGeneration.Gen1, cry: 'Fearow!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ekans: { id: 23, name: 'Ekans', generation: PokemonGeneration.Gen1, cry: 'Ekans!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, arbok: { id: 24, name: 'Arbok', generation: PokemonGeneration.Gen1, cry: 'Arbok!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pikachu: { id: 25, name: 'Pikachu', generation: PokemonGeneration.Gen1, cry: 'Pikachu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pikachu_female: { id: 25, name: 'Pikachu (Female)', generation: PokemonGeneration.Gen1, cry: 'Pikachu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, raichu: { id: 26, name: 'Raichu', generation: PokemonGeneration.Gen1, cry: 'Raichu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sandshrew: { id: 27, name: 'Sandshrew', generation: PokemonGeneration.Gen1, cry: 'Sandshrew!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sandslash: { id: 28, name: 'Sandslash', generation: PokemonGeneration.Gen1, cry: 'Sandslash!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, nidoran_female: { id: 29, name: 'Nidoran♀', generation: PokemonGeneration.Gen1, cry: 'Nidoran!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, nidorina: { id: 30, name: 'Nidorina', generation: PokemonGeneration.Gen1, cry: 'Nidorina!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, nidoqueen: { id: 31, name: 'Nidoqueen', generation: PokemonGeneration.Gen1, cry: 'Nidoqueen!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, nidoran_male: { id: 32, name: 'Nidoran♂', generation: PokemonGeneration.Gen1, cry: 'Nidoran!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, nidorino: { id: 33, name: 'Nidorino', generation: PokemonGeneration.Gen1, cry: 'Nidorino!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, nidoking: { id: 34, name: 'Nidoking', generation: PokemonGeneration.Gen1, cry: 'Nidoking!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, clefairy: { id: 35, name: 'Clefairy', generation: PokemonGeneration.Gen1, cry: 'Clefairy!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, clefable: { id: 36, name: 'Clefable', generation: PokemonGeneration.Gen1, cry: 'Clefable!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, vulpix: { id: 37, name: 'Vulpix', generation: PokemonGeneration.Gen1, cry: 'Vulpix!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ninetales: { id: 38, name: 'Ninetales', generation: PokemonGeneration.Gen1, cry: 'Ninetales!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, jigglypuff: { id: 39, name: 'Jigglypuff', generation: PokemonGeneration.Gen1, cry: 'Jigglypuff!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wigglytuff: { id: 40, name: 'Wigglytuff', generation: PokemonGeneration.Gen1, cry: 'Wigglytuff!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, zubat: { id: 41, name: 'Zubat', generation: PokemonGeneration.Gen1, cry: 'Zubat!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, golbat: { id: 42, name: 'Golbat', generation: PokemonGeneration.Gen1, cry: 'Golbat!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, oddish: { id: 43, name: 'Oddish', generation: PokemonGeneration.Gen1, cry: 'Oddish!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gloom: { id: 44, name: 'Gloom', generation: PokemonGeneration.Gen1, cry: 'Gloom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, vileplume: { id: 45, name: 'Vileplume', generation: PokemonGeneration.Gen1, cry: 'Vileplume!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, paras: { id: 46, name: 'Paras', generation: PokemonGeneration.Gen1, cry: 'Paras!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, parasect: { id: 47, name: 'Parasect', generation: PokemonGeneration.Gen1, cry: 'Parasect!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, venonat: { id: 48, name: 'Venonat', generation: PokemonGeneration.Gen1, cry: 'Venonat!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, venomoth: { id: 49, name: 'Venomoth', generation: PokemonGeneration.Gen1, cry: 'Venomoth!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, diglett: { id: 50, name: 'Diglett', generation: PokemonGeneration.Gen1, cry: 'Diglett!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dugtrio: { id: 51, name: 'Dugtrio', generation: PokemonGeneration.Gen1, cry: 'Dugtrio!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, meowth: { id: 52, name: 'Meowth', generation: PokemonGeneration.Gen1, cry: 'Meowth!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, persian: { id: 53, name: 'Persian', generation: PokemonGeneration.Gen1, cry: 'Persian!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, psyduck: { id: 54, name: 'Psyduck', generation: PokemonGeneration.Gen1, cry: 'Psyduck!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, golduck: { id: 55, name: 'Golduck', generation: PokemonGeneration.Gen1, cry: 'Golduck!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mankey: { id: 56, name: 'Mankey', generation: PokemonGeneration.Gen1, cry: 'Mankey!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, primeape: { id: 57, name: 'Primeape', generation: PokemonGeneration.Gen1, cry: 'Primeape!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, growlithe: { id: 58, name: 'Growlithe', generation: PokemonGeneration.Gen1, cry: 'Growlithe!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, arcanine: { id: 59, name: 'Arcanine', generation: PokemonGeneration.Gen1, cry: 'Arcanine!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, poliwag: { id: 60, name: 'Poliwag', generation: PokemonGeneration.Gen1, cry: 'Poliwag!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, poliwhirl: { id: 61, name: 'Poliwhirl', generation: PokemonGeneration.Gen1, cry: 'Poliwhirl!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, poliwrath: { id: 62, name: 'Poliwrath', generation: PokemonGeneration.Gen1, cry: 'Poliwrath!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, abra: { id: 63, name: 'Abra', generation: PokemonGeneration.Gen1, cry: 'Abra!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kadabra: { id: 64, name: 'Kadabra', generation: PokemonGeneration.Gen1, cry: 'Kadabra!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, alakazam: { id: 65, name: 'Alakazam', generation: PokemonGeneration.Gen1, cry: 'Alakazam!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, machop: { id: 66, name: 'Machop', generation: PokemonGeneration.Gen1, cry: 'Machop!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, machoke: { id: 67, name: 'Machoke', generation: PokemonGeneration.Gen1, cry: 'Machoke!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, machamp: { id: 68, name: 'Machamp', generation: PokemonGeneration.Gen1, cry: 'Alakazam!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, bellsprout: { id: 69, name: 'Bellsprout', generation: PokemonGeneration.Gen1, cry: 'Bellsprout!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, weepinbell: { id: 70, name: 'Weepinbell', generation: PokemonGeneration.Gen1, cry: 'Weepinbell!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, victreebel: { id: 71, name: 'Victreebel', generation: PokemonGeneration.Gen1, cry: 'Victreebel!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, tentacool: { id: 72, name: 'Tentacool', generation: PokemonGeneration.Gen1, cry: 'Tentacool!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, tentacruel: { id: 73, name: 'Tentacruel', generation: PokemonGeneration.Gen1, cry: 'Tentacruel!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, geodude: { id: 74, name: 'Geodude', generation: PokemonGeneration.Gen1, cry: 'Geodude!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, graveler: { id: 75, name: 'Graveler', generation: PokemonGeneration.Gen1, cry: 'Graveler!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, golem: { id: 76, name: 'Golem', generation: PokemonGeneration.Gen1, cry: 'Golem!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ponyta: { id: 77, name: 'Ponyta', generation: PokemonGeneration.Gen1, cry: 'Ponyta!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rapidash: { id: 78, name: 'Rapidash', generation: PokemonGeneration.Gen1, cry: 'Rapidash!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, slowpoke: { id: 79, name: 'Slowpoke', generation: PokemonGeneration.Gen1, cry: 'Slowpoke!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, slowbro: { id: 80, name: 'Slowbro', generation: PokemonGeneration.Gen1, cry: 'Slowbro!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, magnemite: { id: 81, name: 'Magnemite', generation: PokemonGeneration.Gen1, cry: 'Magnemite!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, magneton: { id: 82, name: 'Magneton', generation: PokemonGeneration.Gen1, cry: 'Magneton!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, farfetchd: { id: 83, name: "Farfetch'd", generation: PokemonGeneration.Gen1, cry: "Farfetch'd!", possibleColors: [PokemonColor.default, PokemonColor.shiny], }, doduo: { id: 84, name: 'Doduo', generation: PokemonGeneration.Gen1, cry: 'Doduo!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dodrio: { id: 85, name: 'Dodrio', generation: PokemonGeneration.Gen1, cry: 'Dodrio!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, seel: { id: 86, name: 'Seel', generation: PokemonGeneration.Gen1, cry: 'Seel!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dewgong: { id: 87, name: 'Dewgong', generation: PokemonGeneration.Gen1, cry: 'Dewgong!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, grimer: { id: 88, name: 'Grimer', generation: PokemonGeneration.Gen1, cry: 'Grimer!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, muk: { id: 89, name: 'Muk', generation: PokemonGeneration.Gen1, cry: 'Muk!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shellder: { id: 90, name: 'Shellder', generation: PokemonGeneration.Gen1, cry: 'Shellder!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, cloyster: { id: 91, name: 'Cloyster', generation: PokemonGeneration.Gen1, cry: 'Cloyster!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gastly: { id: 92, name: 'Gastly', generation: PokemonGeneration.Gen1, cry: 'Gastly!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, haunter: { id: 93, name: 'Haunter', generation: PokemonGeneration.Gen1, cry: 'Haunter!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gengar: { id: 94, name: 'Gengar', generation: PokemonGeneration.Gen1, cry: 'Gengar!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, onix: { id: 95, name: 'Onix', generation: PokemonGeneration.Gen1, cry: 'Onix!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, drowzee: { id: 96, name: 'Drowzee', generation: PokemonGeneration.Gen1, cry: 'Drowzee!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hypno: { id: 97, name: 'Hypno', generation: PokemonGeneration.Gen1, cry: 'Hypno!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, krabby: { id: 98, name: 'Krabby', generation: PokemonGeneration.Gen1, cry: 'Krabby!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kingler: { id: 99, name: 'Kingler', generation: PokemonGeneration.Gen1, cry: 'Kingler!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, voltorb: { id: 100, name: 'Voltorb', generation: PokemonGeneration.Gen1, cry: 'Voltorb!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, electrode: { id: 101, name: 'Electrode', generation: PokemonGeneration.Gen1, cry: 'Electrode!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, exeggcute: { id: 102, name: 'Exeggcute', generation: PokemonGeneration.Gen1, cry: 'Exeggcute!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, exeggutor: { id: 103, name: 'Exeggutor', generation: PokemonGeneration.Gen1, cry: 'Exeggutor!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, cubone: { id: 104, name: 'Cubone', generation: PokemonGeneration.Gen1, cry: 'Cubone!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, marowak: { id: 105, name: 'Marowak', generation: PokemonGeneration.Gen1, cry: 'Marowak!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hitmonlee: { id: 106, name: 'Hitmonlee', generation: PokemonGeneration.Gen1, cry: 'Hitmonlee!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hitmonchan: { id: 107, name: 'Hitmonchan', generation: PokemonGeneration.Gen1, cry: 'Hitmonchan!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lickitung: { id: 108, name: 'Lickitung', generation: PokemonGeneration.Gen1, cry: 'Lickitung!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, koffing: { id: 109, name: 'Koffing', generation: PokemonGeneration.Gen1, cry: 'Koffing!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, weezing: { id: 110, name: 'Weezing', generation: PokemonGeneration.Gen1, cry: 'Weezing!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rhyhorn: { id: 111, name: 'Rhyhorn', generation: PokemonGeneration.Gen1, cry: 'Rhyhorn!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rhydon: { id: 112, name: 'Rhydon', generation: PokemonGeneration.Gen1, cry: 'Rhydon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, chansey: { id: 113, name: 'Chansey', generation: PokemonGeneration.Gen1, cry: 'Chansey!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, tangela: { id: 114, name: 'Tangela', generation: PokemonGeneration.Gen1, cry: 'Tangela!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kangaskhan: { id: 115, name: 'Kangaskhan', generation: PokemonGeneration.Gen1, cry: 'Kangaskhan!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, horsea: { id: 116, name: 'Horsea', generation: PokemonGeneration.Gen1, cry: 'Horsea!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, seadra: { id: 117, name: 'Seadra', generation: PokemonGeneration.Gen1, cry: 'Seadra!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, goldeen: { id: 118, name: 'Goldeen', generation: PokemonGeneration.Gen1, cry: 'Goldeen!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, seaking: { id: 119, name: 'Seaking', generation: PokemonGeneration.Gen1, cry: 'Seaking!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, staryu: { id: 120, name: 'Staryu', generation: PokemonGeneration.Gen1, cry: 'Staryu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, starmie: { id: 121, name: 'Starmie', generation: PokemonGeneration.Gen1, cry: 'Starmie!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mrmime: { id: 122, name: 'Mr. Mime', generation: PokemonGeneration.Gen1, cry: 'Mr. Mime!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, scyther: { id: 123, name: 'Scyther', generation: PokemonGeneration.Gen1, cry: 'Scyther!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, jynx: { id: 124, name: 'Jynx', generation: PokemonGeneration.Gen1, cry: 'Jynx!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, electabuzz: { id: 125, name: 'Electabuzz', generation: PokemonGeneration.Gen1, cry: 'Electabuzz!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, magmar: { id: 126, name: 'Magmar', generation: PokemonGeneration.Gen1, cry: 'Magmar!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pinsir: { id: 127, name: 'Pinsir', generation: PokemonGeneration.Gen1, cry: 'Pinsir!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, tauros: { id: 128, name: 'Tauros', generation: PokemonGeneration.Gen1, cry: 'Tauros!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, magikarp: { id: 129, name: 'Magikarp', generation: PokemonGeneration.Gen1, cry: 'Magikarp!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gyarados: { id: 130, name: 'Gyarados', generation: PokemonGeneration.Gen1, cry: 'Gyarados!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lapras: { id: 131, name: 'Lapras', generation: PokemonGeneration.Gen1, cry: 'Lapras!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ditto: { id: 132, name: 'Ditto', generation: PokemonGeneration.Gen1, cry: 'Ditto!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, eevee: { id: 133, name: 'Eevee', generation: PokemonGeneration.Gen1, cry: 'Eevee!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, vaporeon: { id: 134, name: 'Vaporeon', generation: PokemonGeneration.Gen1, cry: 'Vaporeon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, jolteon: { id: 135, name: 'Jolteon', generation: PokemonGeneration.Gen1, cry: 'Jolteon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, flareon: { id: 136, name: 'Flareon', generation: PokemonGeneration.Gen1, cry: 'Flareon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, porygon: { id: 137, name: 'Porygon', generation: PokemonGeneration.Gen1, cry: 'Porygon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, omanyte: { id: 138, name: 'Omanyte', generation: PokemonGeneration.Gen1, cry: 'Omanyte!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, omastar: { id: 139, name: 'Omastar', generation: PokemonGeneration.Gen1, cry: 'Omastar!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kabuto: { id: 140, name: 'Kabuto', generation: PokemonGeneration.Gen1, cry: 'Kabuto!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kabutops: { id: 141, name: 'Kabutops', generation: PokemonGeneration.Gen1, cry: 'Kabutops!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, aerodactyl: { id: 142, name: 'Aerodactyl', generation: PokemonGeneration.Gen1, cry: 'Aerodactyl!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, snorlax: { id: 143, name: 'Snorlax', generation: PokemonGeneration.Gen1, cry: 'Snorlax!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, articuno: { id: 144, name: 'Articuno', generation: PokemonGeneration.Gen1, cry: 'Articuno!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, zapdos: { id: 145, name: 'Zapdos', generation: PokemonGeneration.Gen1, cry: 'Zapdos!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, moltres: { id: 146, name: 'Moltres', generation: PokemonGeneration.Gen1, cry: 'Moltres!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dratini: { id: 147, name: 'Dratini', generation: PokemonGeneration.Gen1, cry: 'Dratini!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dragonair: { id: 148, name: 'Dragonair', generation: PokemonGeneration.Gen1, cry: 'Dragonair!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dragonite: { id: 149, name: 'Dragonite', generation: PokemonGeneration.Gen1, cry: 'Dragonite!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mewtwo: { id: 150, name: 'Mewtwo', generation: PokemonGeneration.Gen1, cry: 'Mewtwo!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mew: { id: 151, name: 'Mew', generation: PokemonGeneration.Gen1, cry: 'Mew!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, // Generation 2 chikorita: { id: 152, name: 'Chikorita', generation: PokemonGeneration.Gen2, cry: 'Chikorita!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, bayleef: { id: 153, name: 'Bayleef', generation: PokemonGeneration.Gen2, cry: 'Bayleef!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, meganium: { id: 154, name: 'Meganium', generation: PokemonGeneration.Gen2, cry: 'Meganium!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, meganium_female: { id: 154, name: 'Meganium (Female)', generation: PokemonGeneration.Gen2, cry: 'Meganium!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, cyndaquil: { id: 155, name: 'Cyndaquil', generation: PokemonGeneration.Gen2, cry: 'Cyndaquil!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, quilava: { id: 156, name: 'Quilava', generation: PokemonGeneration.Gen2, cry: 'Quilava!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, typhlosion: { id: 157, name: 'Typhlosion', generation: PokemonGeneration.Gen2, cry: 'Typhlosion!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, totodile: { id: 158, name: 'Totodile', generation: PokemonGeneration.Gen2, cry: 'Totodile!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, croconaw: { id: 159, name: 'Croconaw', generation: PokemonGeneration.Gen2, cry: 'Croconaw!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, feraligatr: { id: 160, name: 'Feraligatr', generation: PokemonGeneration.Gen2, cry: 'Feraligatr!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sentret: { id: 161, name: 'Sentret', generation: PokemonGeneration.Gen2, cry: 'Sentret!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, furret: { id: 162, name: 'Furret', generation: PokemonGeneration.Gen2, cry: 'Furret!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hoothoot: { id: 163, name: 'Hoothoot', generation: PokemonGeneration.Gen2, cry: 'Hoothoot!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, noctowl: { id: 164, name: 'Noctowl', generation: PokemonGeneration.Gen2, cry: 'Noctowl!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ledyba: { id: 165, name: 'Ledyba', generation: PokemonGeneration.Gen2, cry: 'Ledyba!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ledian: { id: 166, name: 'Ledian', generation: PokemonGeneration.Gen2, cry: 'Ledian!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, spinarak: { id: 167, name: 'Spinarak', generation: PokemonGeneration.Gen2, cry: 'Spinarak!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ariados: { id: 168, name: 'Ariados', generation: PokemonGeneration.Gen2, cry: 'Ariados!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, crobat: { id: 169, name: 'Crobat', generation: PokemonGeneration.Gen2, cry: 'Crobat!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, chinchou: { id: 170, name: 'Chinchou', generation: PokemonGeneration.Gen2, cry: 'Chinchou!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lanturn: { id: 171, name: 'Lanturn', generation: PokemonGeneration.Gen2, cry: 'Lanturn!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pichu: { id: 172, name: 'Pichu', generation: PokemonGeneration.Gen2, cry: 'Pichu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pichu_spiky_eared: { id: 172, name: 'Pichu (Spiky-eared)', generation: PokemonGeneration.Gen2, cry: 'Pichu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, cleffa: { id: 173, name: 'Cleffa', generation: PokemonGeneration.Gen2, cry: 'Cleffa!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, igglybuff: { id: 174, name: 'Igglybuff', generation: PokemonGeneration.Gen2, cry: 'Igglybuff!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, togepi: { id: 175, name: 'Togepi', generation: PokemonGeneration.Gen2, cry: 'Togepi!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, togetic: { id: 176, name: 'Togetic', generation: PokemonGeneration.Gen2, cry: 'Togetic!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, natu: { id: 177, name: 'Natu', generation: PokemonGeneration.Gen2, cry: 'Natu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, xatu: { id: 178, name: 'Xatu', generation: PokemonGeneration.Gen2, cry: 'Xatu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mareep: { id: 179, name: 'Mareep', generation: PokemonGeneration.Gen2, cry: 'Mareep!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, flaaffy: { id: 180, name: 'Flaaffy', generation: PokemonGeneration.Gen2, cry: 'Flaaffy!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ampharos: { id: 181, name: 'Ampharos', generation: PokemonGeneration.Gen2, cry: 'Ampharos!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, bellossom: { id: 182, name: 'Bellossom', generation: PokemonGeneration.Gen2, cry: 'Bellossom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, marill: { id: 183, name: 'Marill', generation: PokemonGeneration.Gen2, cry: 'Marill!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, azumarill: { id: 184, name: 'Azumarill', generation: PokemonGeneration.Gen2, cry: 'Azumarill!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sudowoodo: { id: 185, name: 'Sudowoodo', generation: PokemonGeneration.Gen2, cry: 'Sudowoodo!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, politoed: { id: 186, name: 'Politoed', generation: PokemonGeneration.Gen2, cry: 'Politoed!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hoppip: { id: 187, name: 'Hoppip', generation: PokemonGeneration.Gen2, cry: 'Hoppip!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, skiploom: { id: 188, name: 'Skiploom', generation: PokemonGeneration.Gen2, cry: 'Skiploom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, jumpluff: { id: 189, name: 'Jumpluff', generation: PokemonGeneration.Gen2, cry: 'Jumpluff!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, aipom: { id: 190, name: 'Aipom', generation: PokemonGeneration.Gen2, cry: 'Aipom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sunkern: { id: 191, name: 'Sunkern', generation: PokemonGeneration.Gen2, cry: 'Sunkern!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sunflora: { id: 192, name: 'Sunflora', generation: PokemonGeneration.Gen2, cry: 'Sunflora!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, yanma: { id: 193, name: 'Yanma', generation: PokemonGeneration.Gen2, cry: 'Yanma!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wooper: { id: 194, name: 'Wooper', generation: PokemonGeneration.Gen2, cry: 'Wooper!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, quagsire: { id: 195, name: 'Quagsire', generation: PokemonGeneration.Gen2, cry: 'Quagsire!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, espeon: { id: 196, name: 'Espeon', generation: PokemonGeneration.Gen2, cry: 'Espeon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, umbreon: { id: 197, name: 'Umbreon', generation: PokemonGeneration.Gen2, cry: 'Umbreon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, murkrow: { id: 198, name: 'Murkrow', generation: PokemonGeneration.Gen2, cry: 'Murkrow!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, slowking: { id: 199, name: 'Slowking', generation: PokemonGeneration.Gen2, cry: 'Slowking!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, misdreavus: { id: 200, name: 'Misdreavus', generation: PokemonGeneration.Gen2, cry: 'Misdreavus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_a: { id: 201, name: 'Unown A', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_b: { id: 201, name: 'Unown B', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_c: { id: 201, name: 'Unown C', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_d: { id: 201, name: 'Unown D', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_e: { id: 201, name: 'Unown E', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_f: { id: 201, name: 'Unown F', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_g: { id: 201, name: 'Unown G', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_h: { id: 201, name: 'Unown H', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_i: { id: 201, name: 'Unown I', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_j: { id: 201, name: 'Unown J', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_k: { id: 201, name: 'Unown K', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_l: { id: 201, name: 'Unown L', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_m: { id: 201, name: 'Unown M', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_n: { id: 201, name: 'Unown N', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_o: { id: 201, name: 'Unown O', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_p: { id: 201, name: 'Unown P', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_q: { id: 201, name: 'Unown Q', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_r: { id: 201, name: 'Unown R', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_s: { id: 201, name: 'Unown S', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_t: { id: 201, name: 'Unown T', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_u: { id: 201, name: 'Unown U', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_v: { id: 201, name: 'Unown V', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_w: { id: 201, name: 'Unown W', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_x: { id: 201, name: 'Unown X', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_y: { id: 201, name: 'Unown Y', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_z: { id: 201, name: 'Unown Z', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_exclamation: { id: 201, name: 'Unown !', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, unown_question: { id: 201, name: 'Unown ?', generation: PokemonGeneration.Gen2, cry: 'Unown!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wobbuffet_male: { id: 202, name: 'Wobbuffet (Male)', generation: PokemonGeneration.Gen2, cry: 'Wobbuffet!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wobbuffet_female: { id: 202, name: 'Wobbuffet (Female)', generation: PokemonGeneration.Gen2, cry: 'Wobbuffet!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, girafarig: { id: 203, name: 'Girafarig', generation: PokemonGeneration.Gen2, cry: 'Girafarig!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pineco: { id: 204, name: 'Pineco', generation: PokemonGeneration.Gen2, cry: 'Pineco!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, forretress: { id: 205, name: 'Forretress', generation: PokemonGeneration.Gen2, cry: 'Forretress!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dunsparce: { id: 206, name: 'Dunsparce', generation: PokemonGeneration.Gen2, cry: 'Dunsparce!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gligar: { id: 207, name: 'Gligar', generation: PokemonGeneration.Gen2, cry: 'Gligar!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, steelix: { id: 208, name: 'Steelix', generation: PokemonGeneration.Gen2, cry: 'Steelix!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, steelix_female: { id: 208, name: 'Steelix (Female)', generation: PokemonGeneration.Gen2, cry: 'Steelix!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, snubbull: { id: 209, name: 'Snubbull', generation: PokemonGeneration.Gen2, cry: 'Snubbull!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, granbull: { id: 210, name: 'Granbull', generation: PokemonGeneration.Gen2, cry: 'Granbull!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, qwilfish: { id: 211, name: 'Qwilfish', generation: PokemonGeneration.Gen2, cry: 'Qwilfish!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, scizor: { id: 212, name: 'Scizor', generation: PokemonGeneration.Gen2, cry: 'Scizor!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shuckle: { id: 213, name: 'Shuckle', generation: PokemonGeneration.Gen2, cry: 'Shuckle!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, heracross_male: { id: 214, name: 'Heracross (Male)', generation: PokemonGeneration.Gen2, cry: 'Heracross!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, heracross_female: { id: 214, name: 'Heracross (Female)', generation: PokemonGeneration.Gen2, cry: 'Heracross!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sneasel: { id: 215, name: 'Sneasel', generation: PokemonGeneration.Gen2, cry: 'Sneasel!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, teddiursa: { id: 216, name: 'Teddiursa', generation: PokemonGeneration.Gen2, cry: 'Teddiursa!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ursaring: { id: 217, name: 'Ursaring', generation: PokemonGeneration.Gen2, cry: 'Ursaring!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, slugma: { id: 218, name: 'Slugma', generation: PokemonGeneration.Gen2, cry: 'Slugma!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, magcargo: { id: 219, name: 'Magcargo', generation: PokemonGeneration.Gen2, cry: 'Magcargo!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, swinub: { id: 220, name: 'Swinub', generation: PokemonGeneration.Gen2, cry: 'Swinub!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, piloswine: { id: 221, name: 'Piloswine', generation: PokemonGeneration.Gen2, cry: 'Piloswine!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, corsola: { id: 222, name: 'Corsola', generation: PokemonGeneration.Gen2, cry: 'Corsola!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, remoraid: { id: 223, name: 'Remoraid', generation: PokemonGeneration.Gen2, cry: 'Remoraid!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, octillery: { id: 224, name: 'Octillery', generation: PokemonGeneration.Gen2, cry: 'Octillery!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, delibird: { id: 225, name: 'Delibird', generation: PokemonGeneration.Gen2, cry: 'Delibird!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mantine: { id: 226, name: 'Mantine', generation: PokemonGeneration.Gen2, cry: 'Mantine!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, skarmory: { id: 227, name: 'Skarmory', generation: PokemonGeneration.Gen2, cry: 'Skarmory!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, houndour: { id: 228, name: 'Houndour', generation: PokemonGeneration.Gen2, cry: 'Houndour!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, houndoom: { id: 229, name: 'Houndoom', generation: PokemonGeneration.Gen2, cry: 'Houndoom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kingdra: { id: 230, name: 'Kingdra', generation: PokemonGeneration.Gen2, cry: 'Kingdra!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, phanpy: { id: 231, name: 'Phanpy', generation: PokemonGeneration.Gen2, cry: 'Phanpy!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, donphan: { id: 232, name: 'Donphan', generation: PokemonGeneration.Gen2, cry: 'Donphan!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, porygon2: { id: 233, name: 'Porygon2', generation: PokemonGeneration.Gen2, cry: 'Porygon2!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, stantler: { id: 234, name: 'Stantler', generation: PokemonGeneration.Gen2, cry: 'Stantler!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, smeargle: { id: 235, name: 'Smeargle', generation: PokemonGeneration.Gen2, cry: 'Smeargle!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, tyrogue: { id: 236, name: 'Tyrogue', generation: PokemonGeneration.Gen2, cry: 'Tyrogue!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hitmontop: { id: 237, name: 'Hitmontop', generation: PokemonGeneration.Gen2, cry: 'Hitmontop!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, smoochum: { id: 238, name: 'Smoochum', generation: PokemonGeneration.Gen2, cry: 'Smoochum!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, elekid: { id: 239, name: 'Elekid', generation: PokemonGeneration.Gen2, cry: 'Elekid!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, magby: { id: 240, name: 'Magby', generation: PokemonGeneration.Gen2, cry: 'Magby!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, miltank: { id: 241, name: 'Miltank', generation: PokemonGeneration.Gen2, cry: 'Miltank!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, blissey: { id: 242, name: 'Blissey', generation: PokemonGeneration.Gen2, cry: 'Blissey!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, raikou: { id: 243, name: 'Raikou', generation: PokemonGeneration.Gen2, cry: 'Raikou!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, entei: { id: 244, name: 'Entei', generation: PokemonGeneration.Gen2, cry: 'Entei!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, suicune: { id: 245, name: 'Suicune', generation: PokemonGeneration.Gen2, cry: 'Suicune!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, larvitar: { id: 246, name: 'Larvitar', generation: PokemonGeneration.Gen2, cry: 'Larvitar!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pupitar: { id: 247, name: 'Pupitar', generation: PokemonGeneration.Gen2, cry: 'Pupitar!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, tyranitar: { id: 248, name: 'Tyranitar', generation: PokemonGeneration.Gen2, cry: 'Tyranitar!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lugia: { id: 249, name: 'Lugia', generation: PokemonGeneration.Gen2, cry: 'Lugia!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, hooh: { id: 250, name: 'Ho-Oh', generation: PokemonGeneration.Gen2, cry: 'Ho-Oh!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, celebi: { id: 251, name: 'Celebi', generation: PokemonGeneration.Gen2, cry: 'Celebi!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, // Generation 3 treecko: { id: 252, name: 'Treecko', generation: PokemonGeneration.Gen3, cry: 'Treecko!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, grovyle: { id: 253, name: 'Grovyle', generation: PokemonGeneration.Gen3, cry: 'Grovyle!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sceptile: { id: 254, name: 'Sceptile', generation: PokemonGeneration.Gen3, cry: 'Sceptile!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, torchic: { id: 255, name: 'Torchic', generation: PokemonGeneration.Gen3, cry: 'Torchic!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, combusken: { id: 256, name: 'Combusken', generation: PokemonGeneration.Gen3, cry: 'Combusken!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, blaziken: { id: 257, name: 'Blaziken', generation: PokemonGeneration.Gen3, cry: 'Blaziken!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mudkip: { id: 258, name: 'Mudkip', generation: PokemonGeneration.Gen3, cry: 'Mudkip!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, marshtomp: { id: 259, name: 'Marshtomp', generation: PokemonGeneration.Gen3, cry: 'Marshtomp!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, swampert: { id: 260, name: 'Swampert', generation: PokemonGeneration.Gen3, cry: 'Swampert!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, poochyena: { id: 261, name: 'Poochyena', generation: PokemonGeneration.Gen3, cry: 'Poochyena!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mightyena: { id: 262, name: 'Mightyena', generation: PokemonGeneration.Gen3, cry: 'Mightyena!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, zigzagoon: { id: 263, name: 'Zigzagoon', generation: PokemonGeneration.Gen3, cry: 'Zigzagoon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, linoone: { id: 264, name: 'Linoone', generation: PokemonGeneration.Gen3, cry: 'Linoone!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wurmple: { id: 265, name: 'Wurmple', generation: PokemonGeneration.Gen3, cry: 'Wurmple!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, silcoon: { id: 266, name: 'Silcoon', generation: PokemonGeneration.Gen3, cry: 'Silcoon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, beautifly: { id: 267, name: 'Beautifly', generation: PokemonGeneration.Gen3, cry: 'Beautifly!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, cascoon: { id: 268, name: 'Cascoon', generation: PokemonGeneration.Gen3, cry: 'Cascoon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dustox: { id: 269, name: 'Dustox', generation: PokemonGeneration.Gen3, cry: 'Dustox!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lotad: { id: 270, name: 'Lotad', generation: PokemonGeneration.Gen3, cry: 'Lotad!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lombre: { id: 271, name: 'Lombre', generation: PokemonGeneration.Gen3, cry: 'Lombre!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ludicolo: { id: 272, name: 'Ludicolo', generation: PokemonGeneration.Gen3, cry: 'Ludicolo!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, seedot: { id: 273, name: 'Seedot', generation: PokemonGeneration.Gen3, cry: 'Seedot!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, nuzleaf: { id: 274, name: 'Nuzleaf', generation: PokemonGeneration.Gen3, cry: 'Nuzleaf!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shiftry: { id: 275, name: 'Shiftry', generation: PokemonGeneration.Gen3, cry: 'Shiftry!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, taillow: { id: 276, name: 'Taillow', generation: PokemonGeneration.Gen3, cry: 'Taillow!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, swellow: { id: 277, name: 'Swellow', generation: PokemonGeneration.Gen3, cry: 'Swellow!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wingull: { id: 278, name: 'Wingull', generation: PokemonGeneration.Gen3, cry: 'Wingull!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pelipper: { id: 279, name: 'Pelipper', generation: PokemonGeneration.Gen3, cry: 'Pelipper!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ralts: { id: 280, name: 'Ralts', generation: PokemonGeneration.Gen3, cry: 'Ralts!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kirlia: { id: 281, name: 'Kirlia', generation: PokemonGeneration.Gen3, cry: 'Kirlia!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gardevoir: { id: 282, name: 'Gardevoir', generation: PokemonGeneration.Gen3, cry: 'Gardevoir!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, surskit: { id: 283, name: 'Surskit', generation: PokemonGeneration.Gen3, cry: 'Surskit!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, masquerain: { id: 284, name: 'Masquerain', generation: PokemonGeneration.Gen3, cry: 'Masquerain!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shroomish: { id: 285, name: 'Shroomish', generation: PokemonGeneration.Gen3, cry: 'Shroomish!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, breloom: { id: 286, name: 'Breloom', generation: PokemonGeneration.Gen3, cry: 'Breloom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, slakoth: { id: 287, name: 'Slakoth', generation: PokemonGeneration.Gen3, cry: 'Slakoth!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, vigoroth: { id: 288, name: 'Vigoroth', generation: PokemonGeneration.Gen3, cry: 'Vigoroth!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, slaking: { id: 289, name: 'Slaking', generation: PokemonGeneration.Gen3, cry: 'Slaking!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, nincada: { id: 290, name: 'Nincada', generation: PokemonGeneration.Gen3, cry: 'Nincada!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ninjask: { id: 291, name: 'Ninjask', generation: PokemonGeneration.Gen3, cry: 'Ninjask!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shedinja: { id: 292, name: 'Shedinja', generation: PokemonGeneration.Gen3, cry: 'Shedinja!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, whismur: { id: 293, name: 'Whismur', generation: PokemonGeneration.Gen3, cry: 'Whismur!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, loudred: { id: 294, name: 'Loudred', generation: PokemonGeneration.Gen3, cry: 'Loudred!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, exploud: { id: 295, name: 'Exploud', generation: PokemonGeneration.Gen3, cry: 'Exploud!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, makuhita: { id: 296, name: 'Makuhita', generation: PokemonGeneration.Gen3, cry: 'Makuhita!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hariyama: { id: 297, name: 'Hariyama', generation: PokemonGeneration.Gen3, cry: 'Hariyama!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, azurill: { id: 298, name: 'Azurill', generation: PokemonGeneration.Gen3, cry: 'Azurill!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, nosepass: { id: 299, name: 'Nosepass', generation: PokemonGeneration.Gen3, cry: 'Nosepass!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, skitty: { id: 300, name: 'Skitty', generation: PokemonGeneration.Gen3, cry: 'Skitty!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, delcatty: { id: 301, name: 'Delcatty', generation: PokemonGeneration.Gen3, cry: 'Delcatty!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sableye: { id: 302, name: 'Sableye', generation: PokemonGeneration.Gen3, cry: 'Sableye!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mawile: { id: 303, name: 'Mawile', generation: PokemonGeneration.Gen3, cry: 'Mawile!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, aron: { id: 304, name: 'Aron', generation: PokemonGeneration.Gen3, cry: 'Aron!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lairon: { id: 305, name: 'Lairon', generation: PokemonGeneration.Gen3, cry: 'Lairon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, aggron: { id: 306, name: 'Aggron', generation: PokemonGeneration.Gen3, cry: 'Aggron!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, meditite: { id: 307, name: 'Meditite', generation: PokemonGeneration.Gen3, cry: 'Meditite!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, medicham: { id: 308, name: 'Medicham', generation: PokemonGeneration.Gen3, cry: 'Medicham!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, electrike: { id: 309, name: 'Electrike', generation: PokemonGeneration.Gen3, cry: 'Electrike!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, manectric: { id: 310, name: 'Manectric', generation: PokemonGeneration.Gen3, cry: 'Manectric!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, plusle: { id: 311, name: 'Plusle', generation: PokemonGeneration.Gen3, cry: 'Plusle!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, minun: { id: 312, name: 'Minun', generation: PokemonGeneration.Gen3, cry: 'Minun!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, volbeat: { id: 313, name: 'Volbeat', generation: PokemonGeneration.Gen3, cry: 'Volbeat!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, illumise: { id: 314, name: 'Illumise', generation: PokemonGeneration.Gen3, cry: 'Illumise!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, roselia: { id: 315, name: 'Roselia', generation: PokemonGeneration.Gen3, cry: 'Roselia!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gulpin: { id: 316, name: 'Gulpin', generation: PokemonGeneration.Gen3, cry: 'Gulpin!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, swalot: { id: 317, name: 'Swalot', generation: PokemonGeneration.Gen3, cry: 'Swalot!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, carvanha: { id: 318, name: 'Carvanha', generation: PokemonGeneration.Gen3, cry: 'Carvanha!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sharpedo: { id: 319, name: 'Sharpedo', generation: PokemonGeneration.Gen3, cry: 'Sharpedo!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wailmer: { id: 320, name: 'Wailmer', generation: PokemonGeneration.Gen3, cry: 'Wailmer!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wailord: { id: 321, name: 'Wailord', generation: PokemonGeneration.Gen3, cry: 'Wailord!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, numel: { id: 322, name: 'Numel', generation: PokemonGeneration.Gen3, cry: 'Numel!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, camerupt: { id: 323, name: 'Camerupt', generation: PokemonGeneration.Gen3, cry: 'Camerupt!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, torkoal: { id: 324, name: 'Torkoal', generation: PokemonGeneration.Gen3, cry: 'Torkoal!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, spoink: { id: 325, name: 'Spoink', generation: PokemonGeneration.Gen3, cry: 'Spoink!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, grumpig: { id: 326, name: 'Grumpig', generation: PokemonGeneration.Gen3, cry: 'Grumpig!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, spinda: { id: 327, name: 'Spinda', generation: PokemonGeneration.Gen3, cry: 'Spinda!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, trapinch: { id: 328, name: 'Trapinch', generation: PokemonGeneration.Gen3, cry: 'Trapinch!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, vibrava: { id: 329, name: 'Vibrava', generation: PokemonGeneration.Gen3, cry: 'Vibrava!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, flygon: { id: 330, name: 'Flygon', generation: PokemonGeneration.Gen3, cry: 'Flygon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, cacnea: { id: 331, name: 'Cacnea', generation: PokemonGeneration.Gen3, cry: 'Cacnea!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, cacturne: { id: 332, name: 'Cacturne', generation: PokemonGeneration.Gen3, cry: 'Cacturne!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, swablu: { id: 333, name: 'Swablu', generation: PokemonGeneration.Gen3, cry: 'Swablu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, altaria: { id: 334, name: 'Altaria', generation: PokemonGeneration.Gen3, cry: 'Altaria!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, zangoose: { id: 335, name: 'Zangoose', generation: PokemonGeneration.Gen3, cry: 'Zangoose!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, seviper: { id: 336, name: 'Seviper', generation: PokemonGeneration.Gen3, cry: 'Seviper!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lunatone: { id: 337, name: 'Lunatone', generation: PokemonGeneration.Gen3, cry: 'Lunatone!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, solrock: { id: 338, name: 'Solrock', generation: PokemonGeneration.Gen3, cry: 'Solrock!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, barboach: { id: 339, name: 'Barboach', generation: PokemonGeneration.Gen3, cry: 'Barboach!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, whiscash: { id: 340, name: 'Whiscash', generation: PokemonGeneration.Gen3, cry: 'Whiscash!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, corphish: { id: 341, name: 'Corphish', generation: PokemonGeneration.Gen3, cry: 'Corphish!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, crawdaunt: { id: 342, name: 'Crawdaunt', generation: PokemonGeneration.Gen3, cry: 'Crawdaunt!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, baltoy: { id: 343, name: 'Baltoy', generation: PokemonGeneration.Gen3, cry: 'Baltoy!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, claydol: { id: 344, name: 'Claydol', generation: PokemonGeneration.Gen3, cry: 'Claydol!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lileep: { id: 345, name: 'Lileep', generation: PokemonGeneration.Gen3, cry: 'Lileep!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, cradily: { id: 346, name: 'Cradily', generation: PokemonGeneration.Gen3, cry: 'Cradily!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, anorith: { id: 347, name: 'Anorith', generation: PokemonGeneration.Gen3, cry: 'Anorith!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, armaldo: { id: 348, name: 'Armaldo', generation: PokemonGeneration.Gen3, cry: 'Armaldo!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, feebas: { id: 349, name: 'Feebas', generation: PokemonGeneration.Gen3, cry: 'Feebas!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, milotic: { id: 350, name: 'Milotic', generation: PokemonGeneration.Gen3, cry: 'Milotic!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, castform: { id: 351, name: 'Castform', generation: PokemonGeneration.Gen3, cry: 'Castform!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kecleon: { id: 352, name: 'Kecleon', generation: PokemonGeneration.Gen3, cry: 'Kecleon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shuppet: { id: 353, name: 'Shuppet', generation: PokemonGeneration.Gen3, cry: 'Shuppet!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, banette: { id: 354, name: 'Banette', generation: PokemonGeneration.Gen3, cry: 'Banette!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, duskull: { id: 355, name: 'Duskull', generation: PokemonGeneration.Gen3, cry: 'Duskull!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dusclops: { id: 356, name: 'Dusclops', generation: PokemonGeneration.Gen3, cry: 'Dusclops!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, tropius: { id: 357, name: 'Tropius', generation: PokemonGeneration.Gen3, cry: 'Tropius!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, chimecho: { id: 358, name: 'Chimecho', generation: PokemonGeneration.Gen3, cry: 'Chimecho!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, absol: { id: 359, name: 'Absol', generation: PokemonGeneration.Gen3, cry: 'Absol!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wynaut: { id: 360, name: 'Wynaut', generation: PokemonGeneration.Gen3, cry: 'Wynaut!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, snorunt: { id: 361, name: 'Snorunt', generation: PokemonGeneration.Gen3, cry: 'Snorunt!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, glalie: { id: 362, name: 'Glalie', generation: PokemonGeneration.Gen3, cry: 'Glalie!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, spheal: { id: 363, name: 'Spheal', generation: PokemonGeneration.Gen3, cry: 'Spheal!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, sealeo: { id: 364, name: 'Sealeo', generation: PokemonGeneration.Gen3, cry: 'Sealeo!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, walrein: { id: 365, name: 'Walrein', generation: PokemonGeneration.Gen3, cry: 'Walrein!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, clamperl: { id: 366, name: 'Clamperl', generation: PokemonGeneration.Gen3, cry: 'Clamperl!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, huntail: { id: 367, name: 'Huntail', generation: PokemonGeneration.Gen3, cry: 'Huntail!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gorebyss: { id: 368, name: 'Gorebyss', generation: PokemonGeneration.Gen3, cry: 'Gorebyss!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, relicanth: { id: 369, name: 'Relicanth', generation: PokemonGeneration.Gen3, cry: 'Relicanth!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, luvdisc: { id: 370, name: 'Luvdisc', generation: PokemonGeneration.Gen3, cry: 'Luvdisc!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, bagon: { id: 371, name: 'Bagon', generation: PokemonGeneration.Gen3, cry: 'Bagon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shelgon: { id: 372, name: 'Shelgon', generation: PokemonGeneration.Gen3, cry: 'Shelgon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, salamence: { id: 373, name: 'Salamence', generation: PokemonGeneration.Gen3, cry: 'Salamence!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, beldum: { id: 374, name: 'Beldum', generation: PokemonGeneration.Gen3, cry: 'Beldum!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, metang: { id: 375, name: 'Metang', generation: PokemonGeneration.Gen3, cry: 'Metang!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, metagross: { id: 376, name: 'Metagross', generation: PokemonGeneration.Gen3, cry: 'Metagross!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, regirock: { id: 377, name: 'Regirock', generation: PokemonGeneration.Gen3, cry: 'Regirock!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, regice: { id: 378, name: 'Regice', generation: PokemonGeneration.Gen3, cry: 'Regice!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, registeel: { id: 379, name: 'Registeel', generation: PokemonGeneration.Gen3, cry: 'Registeel!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, latias: { id: 380, name: 'Latias', generation: PokemonGeneration.Gen3, cry: 'Latias!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, latios: { id: 381, name: 'Latios', generation: PokemonGeneration.Gen3, cry: 'Latios!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kyogre: { id: 382, name: 'Kyogre', generation: PokemonGeneration.Gen3, cry: 'Kyogre!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, groudon: { id: 383, name: 'Groudon', generation: PokemonGeneration.Gen3, cry: 'Groudon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, rayquaza: { id: 384, name: 'Rayquaza', generation: PokemonGeneration.Gen3, cry: 'Rayquaza!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, jirachi: { id: 385, name: 'Jirachi', generation: PokemonGeneration.Gen3, cry: 'Jirachi!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, deoxys: { id: 386, name: 'Deoxys', generation: PokemonGeneration.Gen3, cry: 'Deoxys!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, deoxys_speed: { id: 386, name: 'Deoxys (Speed)', generation: PokemonGeneration.Gen3, cry: 'Deoxys!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, deoxys_attack: { id: 386, name: 'Deoxys (Attack)', generation: PokemonGeneration.Gen3, cry: 'Deoxys!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, deoxys_defense: { id: 386, name: 'Deoxys (Defense)', generation: PokemonGeneration.Gen3, cry: 'Deoxys!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, // Generation 4 turtwig: { id: 387, name: 'Turtwig', generation: PokemonGeneration.Gen4, cry: 'Turtwig!', possibleColors: [PokemonColor.default], }, grotle: { id: 388, name: 'Grotle', generation: PokemonGeneration.Gen4, cry: 'Grotle!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, torterra: { id: 389, name: 'Torterra', generation: PokemonGeneration.Gen4, cry: 'Torterra!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, chimchar: { id: 390, name: 'Chimchar', generation: PokemonGeneration.Gen4, cry: 'Chimchar!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, monferno: { id: 391, name: 'Monferno', generation: PokemonGeneration.Gen4, cry: 'Monferno!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, infernape: { id: 392, name: 'Infernape', generation: PokemonGeneration.Gen4, cry: 'Infernape!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, piplup: { id: 393, name: 'Piplup', generation: PokemonGeneration.Gen4, cry: 'Piplup!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, prinplup: { id: 394, name: 'Prinplup', generation: PokemonGeneration.Gen4, cry: 'Prinplup!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, empoleon: { id: 395, name: 'Empoleon', generation: PokemonGeneration.Gen4, cry: 'Empoleon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, starly: { id: 396, name: 'Starly', generation: PokemonGeneration.Gen4, cry: 'Starly!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, staravia: { id: 397, name: 'Staravia', generation: PokemonGeneration.Gen4, cry: 'Staravia!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, staraptor: { id: 398, name: 'Staraptor', generation: PokemonGeneration.Gen4, cry: 'Staraptor!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, bidoof: { id: 399, name: 'Bidoof', generation: PokemonGeneration.Gen4, cry: 'Bidoof!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, bibarel: { id: 400, name: 'Bibarel', generation: PokemonGeneration.Gen4, cry: 'Bibarel!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, kricketot: { id: 401, name: 'Kricketot', generation: PokemonGeneration.Gen4, cry: 'Kricketot!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, kricketune: { id: 402, name: 'Kricketune', generation: PokemonGeneration.Gen4, cry: 'Kricketune!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, shinx: { id: 403, name: 'Shinx', generation: PokemonGeneration.Gen4, cry: 'Shinx!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, luxio: { id: 404, name: 'Luxio', generation: PokemonGeneration.Gen4, cry: 'Luxio!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, luxray: { id: 405, name: 'Luxray', generation: PokemonGeneration.Gen4, cry: 'Luxray!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, budew: { id: 406, name: 'Budew', generation: PokemonGeneration.Gen4, cry: 'Budew!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, roserade: { id: 407, name: 'Roserade', generation: PokemonGeneration.Gen4, cry: 'Roserade!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, cranidos: { id: 408, name: 'Cranidos', generation: PokemonGeneration.Gen4, cry: 'Cranidos!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rampardos: { id: 409, name: 'Rampardos', generation: PokemonGeneration.Gen4, cry: 'Rampardos!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shieldon: { id: 410, name: 'Shieldon', generation: PokemonGeneration.Gen4, cry: 'Shieldon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, bastiodon: { id: 411, name: 'Bastiodon', generation: PokemonGeneration.Gen4, cry: 'Bastiodon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, burmy_plant: { id: 412, name: 'Burmy (Plant)', generation: PokemonGeneration.Gen4, cry: 'Burmy!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, burmy_sandy: { id: 412, name: 'Burmy (Sandy)', generation: PokemonGeneration.Gen4, cry: 'Burmy!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, burmy_trash: { id: 412, name: 'Burmy (Trash)', generation: PokemonGeneration.Gen4, cry: 'Burmy!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wormadam_plant: { id: 413, name: 'Wormadam (Plant)', generation: PokemonGeneration.Gen4, cry: 'Wormadam!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wormadam_sandy: { id: 413, name: 'Wormadam (Sandy)', generation: PokemonGeneration.Gen4, cry: 'Wormadam!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, wormadam_trash: { id: 413, name: 'Wormadam (Trash)', generation: PokemonGeneration.Gen4, cry: 'Wormadam!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mothim: { id: 414, name: 'Mothim', generation: PokemonGeneration.Gen4, cry: 'Mothim!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, combee_male: { id: 415, name: 'Combee (Male)', generation: PokemonGeneration.Gen4, cry: 'Combee!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, combee_female: { id: 415, name: 'Combee (Female)', generation: PokemonGeneration.Gen4, cry: 'Combee!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, vespiquen: { id: 416, name: 'Vespiquen', generation: PokemonGeneration.Gen4, cry: 'Vespiquen!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, pachirisu: { id: 417, name: 'Pachirisu', generation: PokemonGeneration.Gen4, cry: 'Pachirisu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, buizel: { id: 418, name: 'Buizel', generation: PokemonGeneration.Gen4, cry: 'Buizel!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, floatzel: { id: 419, name: 'Floatzel', generation: PokemonGeneration.Gen4, cry: 'Floatzel!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, cherubi: { id: 420, name: 'Cherubi', generation: PokemonGeneration.Gen4, cry: 'Cherubi!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, cherrim: { id: 421, name: 'Cherrim', generation: PokemonGeneration.Gen4, cry: 'Cherrim!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shellos_west: { id: 422, name: 'Shellos (West)', generation: PokemonGeneration.Gen4, cry: 'Shellos!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shellos_east: { id: 422, name: 'Shellos (East)', generation: PokemonGeneration.Gen4, cry: 'Shellos!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gastrodon_west: { id: 423, name: 'Gastrodon (West)', generation: PokemonGeneration.Gen4, cry: 'Gastrodon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gastrodon_east: { id: 423, name: 'Gastrodon (East)', generation: PokemonGeneration.Gen4, cry: 'Gastrodon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, ambipom: { id: 424, name: 'Ambipom', generation: PokemonGeneration.Gen4, cry: 'Ambipom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, drifloon: { id: 425, name: 'Drifloon', generation: PokemonGeneration.Gen4, cry: 'Drifloon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, drifblim: { id: 426, name: 'Drifblim', generation: PokemonGeneration.Gen4, cry: 'Drifblim!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, buneary: { id: 427, name: 'Buneary', generation: PokemonGeneration.Gen4, cry: 'Buneary!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, lopunny: { id: 428, name: 'Lopunny', generation: PokemonGeneration.Gen4, cry: 'Lopunny!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mismagius: { id: 429, name: 'Mismagius', generation: PokemonGeneration.Gen4, cry: 'Mismagius!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, honchkrow: { id: 430, name: 'Honchkrow', generation: PokemonGeneration.Gen4, cry: 'Honchkrow!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, glameow: { id: 431, name: 'Glameow', generation: PokemonGeneration.Gen4, cry: 'Glameow!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, purugly: { id: 432, name: 'Purugly', generation: PokemonGeneration.Gen4, cry: 'Purugly!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, chingling: { id: 433, name: 'Chingling', generation: PokemonGeneration.Gen4, cry: 'Chingling!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, stunky: { id: 434, name: 'Stunky', generation: PokemonGeneration.Gen4, cry: 'Stunky!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, skuntank: { id: 435, name: 'Skuntank', generation: PokemonGeneration.Gen4, cry: 'Skuntank!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, bronzor: { id: 436, name: 'Bronzor', generation: PokemonGeneration.Gen4, cry: 'Bronzor!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, bronzong: { id: 437, name: 'Bronzong', generation: PokemonGeneration.Gen4, cry: 'Bronzong!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, bonsly: { id: 438, name: 'Bonsly', generation: PokemonGeneration.Gen4, cry: 'Bonsly!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mimeJr: { id: 439, name: 'Mime Jr.', generation: PokemonGeneration.Gen4, cry: 'Mime Jr.!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, happiny: { id: 440, name: 'Happiny', generation: PokemonGeneration.Gen4, cry: 'Happiny!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, chatot: { id: 441, name: 'Chatot', generation: PokemonGeneration.Gen4, cry: 'Chatot!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, spiritomb: { id: 442, name: 'Spiritomb', generation: PokemonGeneration.Gen4, cry: 'Spiritomb!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gible: { id: 443, name: 'Gible', generation: PokemonGeneration.Gen4, cry: 'Gible!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, gible_female: { id: 443, name: 'Gible (Female)', generation: PokemonGeneration.Gen4, cry: 'Gible!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, gabite: { id: 444, name: 'Gabite', generation: PokemonGeneration.Gen4, cry: 'Gabite!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gabite_female: { id: 444, name: 'Gabite (Female)', generation: PokemonGeneration.Gen4, cry: 'Gabite!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, garchomp: { id: 445, name: 'Garchomp', generation: PokemonGeneration.Gen4, cry: 'Garchomp!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, garchomp_female: { id: 445, name: 'Garchomp (Female)', generation: PokemonGeneration.Gen4, cry: 'Garchomp!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, munchlax: { id: 446, name: 'Munchlax', generation: PokemonGeneration.Gen4, cry: 'Munchlax!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, riolu: { id: 447, name: 'Riolu', generation: PokemonGeneration.Gen4, cry: 'Riolu!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, lucario: { id: 448, name: 'Lucario', generation: PokemonGeneration.Gen4, cry: 'Lucario!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hippopotas_male: { id: 449, name: 'Hippopotas (Male)', generation: PokemonGeneration.Gen4, cry: 'Hippopotas!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hippopotas_female: { id: 449, name: 'Hippopotas (Female)', generation: PokemonGeneration.Gen4, cry: 'Hippopotas!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hippowdon_male: { id: 450, name: 'Hippowdon (Male)', generation: PokemonGeneration.Gen4, cry: 'Hippowdon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, hippowdon_female: { id: 450, name: 'Hippowdon (Female)', generation: PokemonGeneration.Gen4, cry: 'Hippowdon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, skorupi: { id: 451, name: 'Skorupi', generation: PokemonGeneration.Gen4, cry: 'Skorupi!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, drapion: { id: 452, name: 'Drapion', generation: PokemonGeneration.Gen4, cry: 'Drapion!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, croagunk: { id: 453, name: 'Croagunk', generation: PokemonGeneration.Gen4, cry: 'Croagunk!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, toxicroak: { id: 454, name: 'Toxicroak', generation: PokemonGeneration.Gen4, cry: 'Toxicroak!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, carnivine: { id: 455, name: 'Carnivine', generation: PokemonGeneration.Gen4, cry: 'Carnivine!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, finneon: { id: 456, name: 'Finneon', generation: PokemonGeneration.Gen4, cry: 'Finneon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lumineon: { id: 457, name: 'Lumineon', generation: PokemonGeneration.Gen4, cry: 'Lumineon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mantyke: { id: 458, name: 'Mantyke', generation: PokemonGeneration.Gen4, cry: 'Mantyke!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, snover: { id: 459, name: 'Snover', generation: PokemonGeneration.Gen4, cry: 'Snover!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, abomasnow: { id: 460, name: 'Abomasnow', generation: PokemonGeneration.Gen4, cry: 'Abomasnow!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, weavile: { id: 461, name: 'Weavile', generation: PokemonGeneration.Gen4, cry: 'Weavile!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, magnezone: { id: 462, name: 'Magnezone', generation: PokemonGeneration.Gen4, cry: 'Magnezone!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, lickilicky: { id: 463, name: 'Lickilicky', generation: PokemonGeneration.Gen4, cry: 'Lickilicky!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rhyperior: { id: 464, name: 'Rhyperior', generation: PokemonGeneration.Gen4, cry: 'Rhyperior!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, tangrowth: { id: 465, name: 'Tangrowth', generation: PokemonGeneration.Gen4, cry: 'Tangrowth!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, electivire: { id: 466, name: 'Electivire', generation: PokemonGeneration.Gen4, cry: 'Electivire!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, magmortar: { id: 467, name: 'Magmortar', generation: PokemonGeneration.Gen4, cry: 'Magmortar!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, togekiss: { id: 468, name: 'Togekiss', generation: PokemonGeneration.Gen4, cry: 'Togekiss!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, yanmega: { id: 469, name: 'Yanmega', generation: PokemonGeneration.Gen4, cry: 'Yanmega!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, leafeon: { id: 470, name: 'Leafeon', generation: PokemonGeneration.Gen4, cry: 'Leafeon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, glaceon: { id: 471, name: 'Glaceon', generation: PokemonGeneration.Gen4, cry: 'Glaceon!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gliscor: { id: 472, name: 'Gliscor', generation: PokemonGeneration.Gen4, cry: 'Gliscor!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mamoswine: { id: 473, name: 'Mamoswine', generation: PokemonGeneration.Gen4, cry: 'Mamoswine!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, porygonZ: { id: 474, name: 'Porygon-Z', generation: PokemonGeneration.Gen4, cry: 'Porygon-Z!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, gallade: { id: 475, name: 'Gallade', generation: PokemonGeneration.Gen4, cry: 'Gallade!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, probopass: { id: 476, name: 'Probopass', generation: PokemonGeneration.Gen4, cry: 'Probopass!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dusknoir: { id: 477, name: 'Dusknoir', generation: PokemonGeneration.Gen4, cry: 'Dusknoir!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, froslass: { id: 478, name: 'Froslass', generation: PokemonGeneration.Gen4, cry: 'Froslass!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rotom: { id: 479, name: 'Rotom', generation: PokemonGeneration.Gen4, cry: 'Rotom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rotom_heat: { id: 479, name: 'Rotom (Heat Form)', generation: PokemonGeneration.Gen4, cry: 'Rotom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rotom_wash: { id: 479, name: 'Rotom (Wash Form)', generation: PokemonGeneration.Gen4, cry: 'Rotom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, rotom_frost: { id: 479, name: 'Rotom (Frost Form)', generation: PokemonGeneration.Gen4, cry: 'Rotom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rotom_fan: { id: 479, name: 'Rotom (Fan Form)', generation: PokemonGeneration.Gen4, cry: 'Rotom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, rotom_mow: { id: 479, name: 'Rotom (Mow Form)', generation: PokemonGeneration.Gen4, cry: 'Rotom!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, uxie: { id: 480, name: 'Uxie', generation: PokemonGeneration.Gen4, cry: 'Uxie!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, mesprit: { id: 481, name: 'Mesprit', generation: PokemonGeneration.Gen4, cry: 'Mesprit!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, azelf: { id: 482, name: 'Azelf', generation: PokemonGeneration.Gen4, cry: 'Azelf!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, dialga: { id: 483, name: 'Dialga', generation: PokemonGeneration.Gen4, cry: 'Dialga!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, palkia: { id: 484, name: 'Palkia', generation: PokemonGeneration.Gen4, cry: 'Palkia!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, heatran: { id: 485, name: 'Heatran', generation: PokemonGeneration.Gen4, cry: 'Heatran!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, regigigas: { id: 486, name: 'Regigigas', generation: PokemonGeneration.Gen4, cry: 'Regigigas!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, giratina: { id: 487, name: 'Giratina', generation: PokemonGeneration.Gen4, cry: 'Giratina!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, giratina_origin: { id: 487, name: 'Giratina (Origin Form)', generation: PokemonGeneration.Gen4, cry: 'Giratina!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, cresselia: { id: 488, name: 'Cresselia', generation: PokemonGeneration.Gen4, cry: 'Cresselia!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, phione: { id: 489, name: 'Phione', generation: PokemonGeneration.Gen4, cry: 'Phione!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, manaphy: { id: 490, name: 'Manaphy', generation: PokemonGeneration.Gen4, cry: 'Manaphy!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, darkrai: { id: 491, name: 'Darkrai', generation: PokemonGeneration.Gen4, cry: 'Darkrai!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shaymin: { id: 492, name: 'Shaymin', generation: PokemonGeneration.Gen4, cry: 'Shaymin!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, shaymin_sky: { id: 492, name: 'Shaymin (Sky Form)', generation: PokemonGeneration.Gen4, cry: 'Shaymin!', possibleColors: [PokemonColor.default, PokemonColor.shiny], extraSprites: [PokemonExtraSprite.leftFacing], }, arceus: { id: 493, name: 'Arceus', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_bug: { id: 493, name: 'Arceus (Bug)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], }, arceus_dark: { id: 493, name: 'Arceus (Dark)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_dragon: { id: 493, name: 'Arceus (Dragon)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_electric: { id: 493, name: 'Arceus (Electric)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_fighting: { id: 493, name: 'Arceus (Fighting)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_fire: { id: 493, name: 'Arceus (Fire)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_flying: { id: 493, name: 'Arceus (Flying)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_ghost: { id: 493, name: 'Arceus (Ghost)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_grass: { id: 493, name: 'Arceus (Grass)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_ground: { id: 493, name: 'Arceus (Ground)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_ice: { id: 493, name: 'Arceus (Ice)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_poison: { id: 493, name: 'Arceus (Poison)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_psychic: { id: 493, name: 'Arceus (Psychic)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_rock: { id: 493, name: 'Arceus (Rock)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_steel: { id: 493, name: 'Arceus (Steel)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, arceus_water: { id: 493, name: 'Arceus (Water)', generation: PokemonGeneration.Gen4, cry: 'Arceus!', possibleColors: [PokemonColor.default, PokemonColor.shiny], originalSpriteSize: 64, }, }; export function getAllPokemon(): PokemonType[] { return Object.keys(POKEMON_DATA) as PokemonType[]; } export function getPokemonByGeneration( generation: PokemonGeneration, ): PokemonType[] { return Object.entries(POKEMON_DATA) .filter(([, config]) => config.generation === generation) .map(([key]) => key as PokemonType); } export function getDefaultPokemon(): PokemonType { return 'bulbasaur'; } export function getRandomPokemonConfig(): [PokemonType, PokemonConfig] { const keys = Object.keys(POKEMON_DATA); const randomKey = keys[Math.floor(Math.random() * keys.length)]; return [randomKey as PokemonType, POKEMON_DATA[randomKey]]; } ================================================ FILE: src/common/types.ts ================================================ /* eslint-disable @typescript-eslint/naming-convention */ import { POKEMON_DATA } from './pokemon-data'; export const enum PokemonColor { default = 'default', shiny = 'shiny', null = 'null', } export enum PokemonGeneration { Gen1 = 1, Gen2 = 2, Gen3 = 3, Gen4 = 4, } export type PokemonTypeString = string & keyof typeof POKEMON_DATA; export type PokemonType = PokemonTypeString; export interface PokemonConfig { id: number; name: string; generation: PokemonGeneration; cry: string; possibleColors: PokemonColor[]; originalSpriteSize?: number; extraSprites?: PokemonExtraSprite[]; } export const enum PokemonExtraSprite { leftFacing = 'left_facing', } export const enum PokemonSpeed { still = 0, verySlow = 1, slow = 2, normal = 3, fast = 4, veryFast = 5, } export const enum PokemonSize { nano = 'nano', small = 'small', medium = 'medium', large = 'large', } export const enum ExtPosition { panel = 'panel', explorer = 'explorer', } export const enum Theme { none = 'none', forest = 'forest', castle = 'castle', beach = 'beach', } export const enum ColorThemeKind { light = 1, dark = 2, highContrast = 3, } export class WebviewMessage { text: string; command: string; constructor(text: string, command: string) { this.text = text; this.command = command; } } export const ALL_COLORS = [PokemonColor.default]; export const ALL_SCALES = [ PokemonSize.nano, PokemonSize.small, PokemonSize.medium, PokemonSize.large, ]; export const ALL_THEMES = [Theme.none, Theme.forest, Theme.castle, Theme.beach]; ================================================ FILE: src/extension/extension.ts ================================================ import * as vscode from 'vscode'; import { ColorThemeKind } from 'vscode'; import * as localize from '../common/localize'; import { randomName } from '../common/names'; import { getDefaultPokemon as getDefaultPokemonType, getPokemonByGeneration, getRandomPokemonConfig, POKEMON_DATA, } from '../common/pokemon-data'; import { ALL_COLORS, ALL_SCALES, ALL_THEMES, ExtPosition, PokemonColor, PokemonGeneration, PokemonSize, PokemonType, Theme, WebviewMessage, } from '../common/types'; import { availableColors, normalizeColor } from '../panel/pokemon-collection'; const EXTRA_POKEMON_KEY = 'vscode-pokemon.extra-pokemon'; const EXTRA_POKEMON_KEY_TYPES = EXTRA_POKEMON_KEY + '.types'; const EXTRA_POKEMON_KEY_COLORS = EXTRA_POKEMON_KEY + '.colors'; const EXTRA_POKEMON_KEY_NAMES = EXTRA_POKEMON_KEY + '.names'; const DEFAULT_POKEMON_SCALE = PokemonSize.medium; const DEFAULT_COLOR = PokemonColor.default; const DEFAULT_POKEMON_TYPE = getDefaultPokemonType(); const DEFAULT_POSITION = ExtPosition.panel; const DEFAULT_THEME = Theme.none; class PokemonQuickPickItem implements vscode.QuickPickItem { constructor( public readonly name_: string, public readonly type: string, public readonly color: string, ) { this.name = name_; this.label = name_; this.description = `${color} ${type}`; } name: string; label: string; kind?: vscode.QuickPickItemKind | undefined; description?: string | undefined; detail?: string | undefined; picked?: boolean | undefined; alwaysShow?: boolean | undefined; buttons?: readonly vscode.QuickInputButton[] | undefined; } let webviewViewProvider: PokemonWebviewViewProvider; function getConfiguredSize(): PokemonSize { var size = vscode.workspace .getConfiguration('vscode-pokemon') .get('pokemonSize', DEFAULT_POKEMON_SCALE); if (ALL_SCALES.lastIndexOf(size) === -1) { size = DEFAULT_POKEMON_SCALE; } return size; } function getConfiguredTheme(): Theme { var theme = vscode.workspace .getConfiguration('vscode-pokemon') .get('theme', DEFAULT_THEME); if (ALL_THEMES.lastIndexOf(theme) === -1) { theme = DEFAULT_THEME; } return theme; } function getConfiguredThemeKind(): ColorThemeKind { return vscode.window.activeColorTheme.kind; } function getConfigurationPosition() { return vscode.workspace .getConfiguration('vscode-pokemon') .get('position', DEFAULT_POSITION); } function getThrowWithMouseConfiguration(): boolean { return vscode.workspace .getConfiguration('vscode-pokemon') .get('throwBallWithMouse', true); } function getConfiguredShinyOdds(): number { return vscode.workspace .getConfiguration('vscode-pokemon') .get('shinyOdds', 8192); } function maybeMakeShiny(possibleColors: PokemonColor[]): PokemonColor { if (possibleColors.includes(PokemonColor.shiny)) { const shinyOdds = getConfiguredShinyOdds(); if (Math.floor(Math.random() * shinyOdds) === 0) { return PokemonColor.shiny; } } return possibleColors[0]; } interface IDefaultPokemonConfig { type: PokemonType; name?: string; shiny?: boolean; } function getConfiguredDefaultPokemon(): PokemonSpecification[] { const defaultConfig = vscode.workspace .getConfiguration('vscode-pokemon') .get('defaultPokemon', []); const size = getConfiguredSize(); const result: PokemonSpecification[] = []; for (const config of defaultConfig) { // Validate that the pokemon type exists if (POKEMON_DATA[config.type]) { const name = config.name || randomName(); // If shiny is not specified, default to color to maybeShiny with the pokemon's available colors. If shiny is true, force shiny color. If shiny is false, force default color. let color: PokemonColor; if (config.shiny === undefined) { color = maybeMakeShiny(availableColors(config.type)); } else if (config.shiny) { color = PokemonColor.shiny; } else { color = DEFAULT_COLOR; } result.push(new PokemonSpecification(color, config.type, size, name)); } else { console.warn( `Invalid pokemon type in defaultPokemon config: ${config.type}`, ); } } return result; } function getSessionPokemonCollection( context: vscode.ExtensionContext, ): PokemonSpecification[] { const savedCollection = PokemonSpecification.collectionFromMemento( context, getConfiguredSize(), ); if (savedCollection.length > 0) { return savedCollection; } return getConfiguredDefaultPokemon(); } function getDefaultPokemonForFreshSession( context: vscode.ExtensionContext, ): PokemonSpecification[] { const savedCollection = PokemonSpecification.collectionFromMemento( context, getConfiguredSize(), ); if (savedCollection.length > 0) { return []; } return getConfiguredDefaultPokemon(); } export function shouldSpawnInitialCollection( collection: PokemonSpecification[], ): boolean { return collection.length > 0; } async function spawnAndPersistCollection( context: vscode.ExtensionContext, panel: IPokemonPanel, collection: PokemonSpecification[], ): Promise { collection.forEach((item) => { panel.spawnPokemon(item); }); await storeCollectionAsMemento(context, collection); } function updatePanelThrowWithMouse(): void { const panel = getPokemonPanel(); if (panel !== undefined) { panel.setThrowWithMouse(getThrowWithMouseConfiguration()); } } async function updateExtensionPositionContext() { await vscode.commands.executeCommand( 'setContext', 'vscode-pokemon.position', getConfigurationPosition(), ); } export class PokemonSpecification { color: PokemonColor; type: PokemonType; size: PokemonSize; name: string; generation: string; originalSpriteSize: number; constructor( color: PokemonColor, type: PokemonType, size: PokemonSize, name?: string, generation?: string, ) { this.color = color; this.type = type; this.size = size; if (!name) { this.name = randomName(); } else { this.name = name; } this.generation = generation || `gen${POKEMON_DATA[type].generation}`; this.originalSpriteSize = POKEMON_DATA[type].originalSpriteSize || 32; } static fromConfiguration(): PokemonSpecification { var color = vscode.workspace .getConfiguration('vscode-pokemon') .get('pokemonColor', DEFAULT_COLOR); if (ALL_COLORS.lastIndexOf(color) === -1) { color = DEFAULT_COLOR; } var type = vscode.workspace .getConfiguration('vscode-pokemon') .get('pokemonType', DEFAULT_POKEMON_TYPE); // Use POKEMON_DATA to validate the type if (!POKEMON_DATA[type]) { type = DEFAULT_POKEMON_TYPE; } return new PokemonSpecification(color, type, getConfiguredSize()); } static collectionFromMemento( context: vscode.ExtensionContext, size: PokemonSize, ): PokemonSpecification[] { var contextTypes = context.globalState.get( EXTRA_POKEMON_KEY_TYPES, [], ); var contextColors = context.globalState.get( EXTRA_POKEMON_KEY_COLORS, [], ); var contextNames = context.globalState.get( EXTRA_POKEMON_KEY_NAMES, [], ); var result: PokemonSpecification[] = []; for (let index = 0; index < contextTypes.length; index++) { result.push( new PokemonSpecification( contextColors?.[index] ?? DEFAULT_COLOR, contextTypes[index], size, contextNames[index], ), ); } return result; } } export async function storeCollectionAsMemento( context: vscode.ExtensionContext, collection: PokemonSpecification[], ) { var contextTypes = new Array(collection.length); var contextColors = new Array(collection.length); var contextNames = new Array(collection.length); for (let index = 0; index < collection.length; index++) { contextTypes[index] = collection[index].type; contextColors[index] = collection[index].color; contextNames[index] = collection[index].name; } await context.globalState.update(EXTRA_POKEMON_KEY_TYPES, contextTypes); await context.globalState.update(EXTRA_POKEMON_KEY_COLORS, contextColors); await context.globalState.update(EXTRA_POKEMON_KEY_NAMES, contextNames); context.globalState.setKeysForSync([ EXTRA_POKEMON_KEY_TYPES, EXTRA_POKEMON_KEY_COLORS, EXTRA_POKEMON_KEY_NAMES, ]); } let spawnPokemonStatusBar: vscode.StatusBarItem; interface IPokemonInfo { type: PokemonType; name: string; color: PokemonColor; } function waitForPokemonList(webview: vscode.Webview): Promise { return new Promise((resolve) => { const disposable = webview.onDidReceiveMessage( (message: WebviewMessage) => { if (message.command !== 'list-pokemon') { return; } disposable.dispose(); const pokemonList: IPokemonInfo[] = []; message.text.split('\n').forEach((pokemon) => { if (!pokemon) { return; } var parts = pokemon.split(','); pokemonList.push({ type: parts[0] as PokemonType, name: parts[1], color: parts[2] as PokemonColor, }); }); resolve(pokemonList); }, ); }); } function getPokemonPanel(): IPokemonPanel | undefined { if ( getConfigurationPosition() === ExtPosition.explorer && webviewViewProvider ) { return webviewViewProvider; } else if (PokemonPanel.currentPanel) { return PokemonPanel.currentPanel; } else { return undefined; } } function getWebview(): vscode.Webview | undefined { if ( getConfigurationPosition() === ExtPosition.explorer && webviewViewProvider ) { return webviewViewProvider.getWebview(); } else if (PokemonPanel.currentPanel) { return PokemonPanel.currentPanel.getWebview(); } } export function activate(context: vscode.ExtensionContext) { // Reset the Pokemon translations cache at startup to load the correct language localize.resetPokemonTranslationsCache(); context.subscriptions.push( vscode.commands.registerCommand('vscode-pokemon.start', async () => { if ( getConfigurationPosition() === ExtPosition.explorer && webviewViewProvider ) { await vscode.commands.executeCommand('pokemonView.focus'); } else { const spec = PokemonSpecification.fromConfiguration(); PokemonPanel.createOrShow( context.extensionUri, spec.color, spec.type, spec.size, spec.generation, spec.originalSpriteSize, getConfiguredTheme(), getConfiguredThemeKind(), getThrowWithMouseConfiguration(), ); if (PokemonPanel.currentPanel) { const collection = getSessionPokemonCollection(context); await spawnAndPersistCollection( context, PokemonPanel.currentPanel, collection, ); } } }), ); spawnPokemonStatusBar = vscode.window.createStatusBarItem( vscode.StatusBarAlignment.Right, 100, ); spawnPokemonStatusBar.command = 'vscode-pokemon.spawn-pokemon'; context.subscriptions.push(spawnPokemonStatusBar); context.subscriptions.push( vscode.window.onDidChangeActiveTextEditor(updateStatusBar), ); context.subscriptions.push( vscode.window.onDidChangeTextEditorSelection(updateStatusBar), ); context.subscriptions.push( vscode.window.onDidChangeActiveTextEditor(updateExtensionPositionContext), ); updateStatusBar(); const spec = PokemonSpecification.fromConfiguration(); webviewViewProvider = new PokemonWebviewViewProvider( context, context.extensionUri, spec.color, spec.type, spec.size, spec.generation, spec.originalSpriteSize, getConfiguredTheme(), getConfiguredThemeKind(), getThrowWithMouseConfiguration(), ); updateExtensionPositionContext().catch((e) => { console.error(e); }); context.subscriptions.push( vscode.window.registerWebviewViewProvider( PokemonWebviewViewProvider.viewType, webviewViewProvider, ), ); context.subscriptions.push( vscode.commands.registerCommand( 'vscode-pokemon.delete-pokemon', async () => { const panel = getPokemonPanel(); if (panel === undefined) { await createPokemonPlayground(context); return; } const webview = getWebview(); if (!webview) { return; } const listPromise = waitForPokemonList(webview); panel.listPokemon(); const pokemonList = await listPromise; if (!pokemonList.length) { await vscode.window.showErrorMessage( vscode.l10n.t('There are no pokemon to remove.'), ); return; } const pokemon = await vscode.window.showQuickPick( pokemonList.map((val) => { return new PokemonQuickPickItem(val.name, val.type, val.color); }), { placeHolder: vscode.l10n.t('Select the pokemon to remove.'), }, ); if (pokemon) { panel.deletePokemon(pokemon.name); const collection = pokemonList .filter((item) => { return item.name !== pokemon.name; }) .map((item) => { return new PokemonSpecification( item.color, item.type, PokemonSize.medium, item.name, ); }); await storeCollectionAsMemento(context, collection); } }, ), ); context.subscriptions.push( vscode.commands.registerCommand( 'vscode-pokemon.remove-all-pokemon', async () => { const panel = getPokemonPanel(); if (panel !== undefined) { panel.resetPokemon(); await storeCollectionAsMemento(context, []); } else { await createPokemonPlayground(context); await vscode.window.showInformationMessage( vscode.l10n.t( "A Pokemon Playground has been created. You can now use the 'Remove All Pokemon' Command to remove all Pokemon.", ), ); } }, ), ); context.subscriptions.push( vscode.commands.registerCommand('vscode-pokemon.roll-call', async () => { const panel = getPokemonPanel(); if (panel !== undefined) { panel.rollCall(); } else { await createPokemonPlayground(context); } }), ); context.subscriptions.push( vscode.commands.registerCommand( 'vscode-pokemon.configure-keybindings', async () => { const items: Array = [ { label: vscode.l10n.t('Spawn additional pokemon'), description: 'vscode-pokemon.spawn-pokemon', commandId: 'vscode-pokemon.spawn-pokemon', }, { label: vscode.l10n.t('Spawn random pokemon'), description: 'vscode-pokemon.spawn-random-pokemon', commandId: 'vscode-pokemon.spawn-random-pokemon', }, { label: vscode.l10n.t('Remove pokemon'), description: 'vscode-pokemon.delete-pokemon', commandId: 'vscode-pokemon.delete-pokemon', }, { label: vscode.l10n.t('Remove all pokemon'), description: 'vscode-pokemon.remove-all-pokemon', commandId: 'vscode-pokemon.remove-all-pokemon', }, ]; const picked = await vscode.window.showQuickPick(items, { placeHolder: vscode.l10n.t( 'Select a command to configure its keybinding', ), matchOnDescription: true, }); if (!picked) { return; } await vscode.commands.executeCommand( 'workbench.action.openGlobalKeybindings', picked.commandId, ); }, ), ); context.subscriptions.push( vscode.commands.registerCommand( 'vscode-pokemon.change-pokemon-language', async () => { const config = vscode.workspace.getConfiguration('vscode-pokemon'); const currentLanguage = config.get('pokemonLanguage', 'auto'); // Language display names and flags (official Pokemon languages only) /* eslint-disable @typescript-eslint/naming-convention */ const languageLabels: { [key: string]: { label: string; description: string }; } = { auto: { label: '$(globe) Auto', description: vscode.l10n.t('Use VS Code language'), }, 'en-US': { label: '🇺🇸 English (US)', description: vscode.l10n.t('English names'), }, 'fr-FR': { label: '🇫🇷 Français (FR)', description: vscode.l10n.t('French names'), }, 'de-DE': { label: '🇩🇪 Deutsch (DE)', description: vscode.l10n.t('German names'), }, 'ja-JP': { label: '🇯🇵 日本語 (JP)', description: vscode.l10n.t('Japanese names'), }, } as { [key: string]: { label: string; description: string } }; /* eslint-enable @typescript-eslint/naming-convention */ const languageOptions: Array = [ { label: languageLabels['auto'].label, description: languageLabels['auto'].description, detail: currentLanguage === 'auto' ? vscode.l10n.t('Current') : undefined, value: 'auto', }, ...localize.SUPPORTED_LOCALES.map((locale) => ({ label: languageLabels[locale]?.label || locale, description: languageLabels[locale]?.description || locale, detail: currentLanguage === locale ? vscode.l10n.t('Current') : undefined, value: locale, })), ]; const picked = await vscode.window.showQuickPick(languageOptions, { placeHolder: vscode.l10n.t('Select language for Pokemon names'), }); if (!picked) { return; } // Update configuration persistently await config.update( 'pokemonLanguage', picked.value, vscode.ConfigurationTarget.Global, ); // Reset translation cache to force reload localize.resetPokemonTranslationsCache(); // Preload translations with the new language // This ensures the cache is immediately available const testPokemon: PokemonType = 'bulbasaur'; localize.getLocalizedPokemonName(testPokemon); await vscode.window.showInformationMessage( vscode.l10n.t( 'Pokemon language changed to {0}. The change will persist after restart.', picked.label, ), ); }, ), ); context.subscriptions.push( vscode.commands.registerCommand( 'vscode-pokemon.export-pokemon-list', async () => { const pokemonCollection = PokemonSpecification.collectionFromMemento( context, getConfiguredSize(), ); const pokemonJson = JSON.stringify(pokemonCollection, null, 2); const fileName = `pokemonCollection-${Date.now()}.json`; if (!vscode.workspace.workspaceFolders) { await vscode.window.showErrorMessage( vscode.l10n.t( 'You must have a folder or workspace open to export pokemonCollection.', ), ); return; } const filePath = vscode.Uri.joinPath( vscode.workspace.workspaceFolders[0].uri, fileName, ); const newUri = vscode.Uri.file(fileName).with({ scheme: 'untitled', path: filePath.fsPath, }); await vscode.workspace.openTextDocument(newUri).then(async (doc) => { await vscode.window.showTextDocument(doc).then(async (editor) => { await editor.edit((edit) => { edit.insert(new vscode.Position(0, 0), pokemonJson); }); }); }); }, ), ); context.subscriptions.push( vscode.commands.registerCommand( 'vscode-pokemon.import-pokemon-list', async () => { const options: vscode.OpenDialogOptions = { canSelectMany: false, openLabel: 'Open pokemonCollection.json', filters: { json: ['json'], }, }; const fileUri = await vscode.window.showOpenDialog(options); if (fileUri && fileUri[0]) { console.log('Selected file: ' + fileUri[0].fsPath); try { const fileContents = await vscode.workspace.fs.readFile(fileUri[0]); const pokemonToLoad = JSON.parse( String.fromCharCode.apply(null, Array.from(fileContents)), ); // load the pokemon into the collection var collection = PokemonSpecification.collectionFromMemento( context, getConfiguredSize(), ); // fetch just the pokemon types const panel = getPokemonPanel(); for (let i = 0; i < pokemonToLoad.length; i++) { const pokemon = pokemonToLoad[i]; const pokemonSpec = new PokemonSpecification( normalizeColor(pokemon.color, pokemon.type), pokemon.type, pokemon.size, pokemon.name, ); collection.push(pokemonSpec); if (panel !== undefined) { panel.spawnPokemon(pokemonSpec); } } await storeCollectionAsMemento(context, collection); } catch (e: any) { await vscode.window.showErrorMessage( vscode.l10n.t('Failed to import pokemon: {0}', e?.message), ); } } }, ), ); context.subscriptions.push( vscode.commands.registerCommand( 'vscode-pokemon.spawn-pokemon', async () => { const panel = getPokemonPanel(); if ( getConfigurationPosition() === ExtPosition.explorer && webviewViewProvider ) { await vscode.commands.executeCommand('pokemonView.focus'); } if (panel) { // Dynamic QuickPick: show only generations by default; reveal Pokémon matches when typing const generationItems: Array< vscode.QuickPickItem & { isGeneration: true; gen: PokemonGeneration; } > = Object.values(PokemonGeneration) .filter((gen) => typeof gen === 'number') .map((gen) => ({ label: `$(folder) ${vscode.l10n.t('Generation {0}', gen)}`, description: vscode.l10n.t('Browse Gen {0} Pokemon', gen), isGeneration: true as const, gen: gen as PokemonGeneration, })); const allPokemonOptions: Array< vscode.QuickPickItem & { value: PokemonType; isGeneration: false } > = Object.entries(POKEMON_DATA).map(([type, config]) => ({ label: localize.getLocalizedPokemonName(type as PokemonType), value: type as PokemonType, description: `#${config.id.toString().padStart(4, '0')} - Gen ${config.generation}`, isGeneration: false as const, })); const qp = vscode.window.createQuickPick< vscode.QuickPickItem & { isGeneration?: boolean; gen?: PokemonGeneration; value?: PokemonType; } >(); qp.placeholder = vscode.l10n.t( 'Select a generation or start typing to search for a Pokemon...', ); qp.matchOnDescription = true; const setGenerationOnlyItems = () => { qp.items = [ { label: vscode.l10n.t('Generations'), kind: vscode.QuickPickItemKind.Separator, }, ...generationItems, ]; }; const setWithSearchResults = (query: string) => { const q = query.toLowerCase().trim(); const results = allPokemonOptions.filter( (opt) => opt.label.toLowerCase().includes(q) || (opt.description?.toLowerCase().includes(q) ?? false), ); qp.items = [ { label: vscode.l10n.t('Generations'), kind: vscode.QuickPickItemKind.Separator, }, ...generationItems, { label: vscode.l10n.t('Results'), kind: vscode.QuickPickItemKind.Separator, }, ...results, ]; }; setGenerationOnlyItems(); let selectedPokemonType: | { label: string; value: PokemonType } | undefined; const disposables: vscode.Disposable[] = []; disposables.push( qp.onDidChangeValue((val) => { if (val && val.trim().length > 0) { setWithSearchResults(val); } else { setGenerationOnlyItems(); } }), ); disposables.push( qp.onDidAccept(async () => { const sel = qp.selectedItems[0] as any; if (!sel) { qp.hide(); return; } if (sel.isGeneration) { // Don't hide the first quick pick yet - dispose it manually const pokemonInGeneration = getPokemonByGeneration( sel.gen as PokemonGeneration, ); const pokemonOptions = pokemonInGeneration.map((type) => ({ label: localize.getLocalizedPokemonName(type), value: type, description: `#${POKEMON_DATA[type].id .toString() .padStart(4, '0')}`, })); // Manually dispose the first quick pick to prevent race condition disposables.forEach((d) => d.dispose()); qp.dispose(); const picked = await vscode.window.showQuickPick( pokemonOptions, { placeHolder: vscode.l10n.t('Select a Pokemon'), }, ); if (picked) { selectedPokemonType = picked; // Handle the rest of the flow const possibleColors = availableColors( selectedPokemonType.value, ); const name = await vscode.window.showInputBox({ placeHolder: vscode.l10n.t('Leave blank for a random name'), prompt: vscode.l10n.t('Name your Pokemon'), value: randomName(), }); if (name === undefined) { console.log('Cancelled Spawning Pokemon - No Name Entered'); return; } const spec = new PokemonSpecification( maybeMakeShiny(possibleColors), selectedPokemonType.value, getConfiguredSize(), name, ); panel.spawnPokemon(spec); var collection = PokemonSpecification.collectionFromMemento( context, getConfiguredSize(), ); collection.push(spec); await storeCollectionAsMemento(context, collection); } } else { selectedPokemonType = sel as any; qp.hide(); } }), ); const closed = new Promise((resolve) => { disposables.push( qp.onDidHide(() => { disposables.forEach((d) => d.dispose()); qp.dispose(); resolve(); }), ); }); qp.show(); await closed; if (!selectedPokemonType) { console.log('Cancelled Spawning Pokemon - No Selection'); return; } if (!selectedPokemonType) { console.log('Cancelled Spawning Pokemon - No Pokemon Selected'); return; } // Rest of the existing code const possibleColors = availableColors(selectedPokemonType.value); const name = await vscode.window.showInputBox({ placeHolder: vscode.l10n.t('Leave blank for a random name'), prompt: vscode.l10n.t('Name your Pokemon'), value: randomName(), }); if (name === undefined) { console.log('Cancelled Spawning Pokemon - No Name Entered'); return; } const spec = new PokemonSpecification( maybeMakeShiny(possibleColors), selectedPokemonType.value, getConfiguredSize(), name, ); panel.spawnPokemon(spec); var collection = PokemonSpecification.collectionFromMemento( context, getConfiguredSize(), ); collection.push(spec); await storeCollectionAsMemento(context, collection); } else { await createPokemonPlayground(context); await vscode.window.showInformationMessage( vscode.l10n.t( "A Pokemon Playground has been created. You can now use the 'Spawn Additional Pokemon' Command to add more Pokemon.", ), ); } }, ), ); context.subscriptions.push( vscode.commands.registerCommand( 'vscode-pokemon.spawn-random-pokemon', async () => { const panel = getPokemonPanel(); if ( getConfigurationPosition() === ExtPosition.explorer && webviewViewProvider ) { await vscode.commands.executeCommand('pokemonView.focus'); } if (panel) { var [randomPokemonType, randomPokemonConfig] = getRandomPokemonConfig(); const spec = new PokemonSpecification( maybeMakeShiny(randomPokemonConfig.possibleColors), randomPokemonType, getConfiguredSize(), randomPokemonConfig.name, ); panel.spawnPokemon(spec); var collection = PokemonSpecification.collectionFromMemento( context, getConfiguredSize(), ); collection.push(spec); await storeCollectionAsMemento(context, collection); } else { await createPokemonPlayground(context); await vscode.window.showInformationMessage( vscode.l10n.t( "A Pokemon Playground has been created. You can now use the 'Remove All Pokemon' Command to remove all Pokemon.", ), ); } }, ), ); // Listening to configuration changes context.subscriptions.push( vscode.workspace.onDidChangeConfiguration( (e: vscode.ConfigurationChangeEvent): void => { if ( e.affectsConfiguration('vscode-pokemon.pokemonColor') || e.affectsConfiguration('vscode-pokemon.pokemonType') || e.affectsConfiguration('vscode-pokemon.pokemonSize') || e.affectsConfiguration('vscode-pokemon.theme') || e.affectsConfiguration('workbench.colorTheme') ) { const spec = PokemonSpecification.fromConfiguration(); const panel = getPokemonPanel(); if (panel) { panel.updatePokemonColor(spec.color); panel.updatePokemonSize(spec.size); panel.updatePokemonType(spec.type); panel.updateTheme(getConfiguredTheme(), getConfiguredThemeKind()); panel.update(); } } if (e.affectsConfiguration('vscode-pokemon.position')) { void updateExtensionPositionContext(); } if (e.affectsConfiguration('vscode-pokemon.throwBallWithMouse')) { updatePanelThrowWithMouse(); } if (e.affectsConfiguration('vscode-pokemon.pokemonLanguage')) { // Reset the Pokemon translations cache when the language changes localize.resetPokemonTranslationsCache(); // Update the panel to reflect the new language const panel = getPokemonPanel(); if (panel) { panel.update(); } } }, ), ); if (vscode.window.registerWebviewPanelSerializer) { // Make sure we register a serializer in activation event vscode.window.registerWebviewPanelSerializer(PokemonPanel.viewType, { async deserializeWebviewPanel(webviewPanel: vscode.WebviewPanel) { // Reset the webview options so we use latest uri for `localResourceRoots`. webviewPanel.webview.options = getWebviewOptions(context.extensionUri); const spec = PokemonSpecification.fromConfiguration(); PokemonPanel.revive( webviewPanel, context.extensionUri, spec.color, spec.type, spec.size, spec.generation, spec.originalSpriteSize, getConfiguredTheme(), getConfiguredThemeKind(), getThrowWithMouseConfiguration(), ); if (PokemonPanel.currentPanel) { const collection = getDefaultPokemonForFreshSession(context); if (shouldSpawnInitialCollection(collection)) { await spawnAndPersistCollection( context, PokemonPanel.currentPanel, collection, ); } } }, }); } } function updateStatusBar(): void { spawnPokemonStatusBar.text = `$(squirrel)`; spawnPokemonStatusBar.tooltip = vscode.l10n.t('Spawn Pokemon'); spawnPokemonStatusBar.show(); } export function spawnPokemonDeactivate() { spawnPokemonStatusBar.dispose(); } function getWebviewOptions( extensionUri: vscode.Uri, ): vscode.WebviewOptions & vscode.WebviewPanelOptions { return { // Enable javascript in the webview enableScripts: true, // And restrict the webview to only loading content from our extension's `media` directory. localResourceRoots: [vscode.Uri.joinPath(extensionUri, 'media')], }; } interface IPokemonPanel { // throwBall(): void; resetPokemon(): void; spawnPokemon(spec: PokemonSpecification): void; deletePokemon(pokemonName: string): void; listPokemon(): void; rollCall(): void; themeKind(): vscode.ColorThemeKind; throwBallWithMouse(): boolean; updatePokemonColor(newColor: PokemonColor): void; updatePokemonType(newType: PokemonType): void; updatePokemonSize(newSize: PokemonSize): void; updateTheme(newTheme: Theme, themeKind: vscode.ColorThemeKind): void; update(): void; setThrowWithMouse(newThrowWithMouse: boolean): void; } class PokemonWebviewContainer implements IPokemonPanel { protected _extensionUri: vscode.Uri; protected _disposables: vscode.Disposable[] = []; protected _pokemonColor: PokemonColor; protected _pokemonType: PokemonType; protected _pokemonSize: PokemonSize; protected _pokemonGeneration: string; protected _pokemonOriginalSpriteSize: number; protected _theme: Theme; protected _themeKind: vscode.ColorThemeKind; protected _throwBallWithMouse: boolean; constructor( extensionUri: vscode.Uri, color: PokemonColor, type: PokemonType, size: PokemonSize, generation: string, originalSpriteSize: number, theme: Theme, themeKind: ColorThemeKind, throwBallWithMouse: boolean, ) { this._extensionUri = extensionUri; this._pokemonColor = color; this._pokemonType = type; this._pokemonSize = size; this._pokemonGeneration = generation; this._pokemonOriginalSpriteSize = originalSpriteSize; this._theme = theme; this._themeKind = themeKind; this._throwBallWithMouse = throwBallWithMouse; } public pokemonColor(): PokemonColor { return normalizeColor(this._pokemonColor, this._pokemonType); } public pokemonType(): PokemonType { return this._pokemonType; } public pokemonSize(): PokemonSize { return this._pokemonSize; } public pokemonGeneration(): string { return this._pokemonGeneration; } public pokemonOriginalSpriteSize(): number { return this._pokemonOriginalSpriteSize; } public theme(): Theme { return this._theme; } public themeKind(): vscode.ColorThemeKind { return this._themeKind; } public throwBallWithMouse(): boolean { return this._throwBallWithMouse; } public updatePokemonColor(newColor: PokemonColor) { this._pokemonColor = newColor; } public updatePokemonType(newType: PokemonType) { this._pokemonType = newType; } public updatePokemonSize(newSize: PokemonSize) { this._pokemonSize = newSize; } public updatePokemonGeneration(newGeneration: string) { this._pokemonGeneration = newGeneration; } public updateTheme(newTheme: Theme, themeKind: vscode.ColorThemeKind) { this._theme = newTheme; this._themeKind = themeKind; } public setThrowWithMouse(newThrowWithMouse: boolean): void { this._throwBallWithMouse = newThrowWithMouse; void this.getWebview().postMessage({ command: 'throw-with-mouse', enabled: newThrowWithMouse, }); } public throwBall() { void this.getWebview().postMessage({ command: 'throw-ball', }); } public resetPokemon(): void { void this.getWebview().postMessage({ command: 'reset-pokemon', }); } public spawnPokemon(spec: PokemonSpecification) { void this.getWebview().postMessage({ command: 'spawn-pokemon', type: spec.type, color: spec.color, name: spec.name, generation: spec.generation, originalSpriteSize: spec.originalSpriteSize, }); void this.getWebview().postMessage({ command: 'set-size', size: spec.size, }); } public listPokemon() { void this.getWebview().postMessage({ command: 'list-pokemon' }); } public rollCall(): void { void this.getWebview().postMessage({ command: 'roll-call' }); } public deletePokemon(pokemonName: string) { void this.getWebview().postMessage({ command: 'delete-pokemon', name: pokemonName, }); } protected getWebview(): vscode.Webview { throw new Error('Not implemented'); } protected _update() { const webview = this.getWebview(); webview.html = this._getHtmlForWebview(webview); } // #TODO: verify if this is needed // eslint-disable-next-line @typescript-eslint/no-empty-function public update() {} protected _getHtmlForWebview(webview: vscode.Webview) { // Local path to main script run in the webview const scriptPathOnDisk = vscode.Uri.joinPath( this._extensionUri, 'media', 'main-bundle.js', ); // And the uri we use to load this script in the webview const scriptUri = webview.asWebviewUri(scriptPathOnDisk); // Local path to css styles const styleResetPath = vscode.Uri.joinPath( this._extensionUri, 'media', 'reset.css', ); const stylesPathMainPath = vscode.Uri.joinPath( this._extensionUri, 'media', 'pokemon.css', ); const silkScreenFontPath = webview.asWebviewUri( vscode.Uri.joinPath( this._extensionUri, 'media', 'Silkscreen-Regular.ttf', ), ); // Uri to load styles into webview const stylesResetUri = webview.asWebviewUri(styleResetPath); const stylesMainUri = webview.asWebviewUri(stylesPathMainPath); // Get path to resource on disk const basePokemonUri = webview.asWebviewUri( vscode.Uri.joinPath(this._extensionUri, 'media'), ); // Use a nonce to only allow specific scripts to be run const nonce = getNonce(); return ` VS Code Pokemon
`; } } function handleWebviewMessage(message: WebviewMessage) { switch (message.command) { case 'alert': void vscode.window.showErrorMessage(message.text); return; case 'info': void vscode.window.showInformationMessage(message.text); return; } } /** * Manages pokemon coding webview panels */ class PokemonPanel extends PokemonWebviewContainer implements IPokemonPanel { /** * Track the currently panel. Only allow a single panel to exist at a time. */ public static currentPanel: PokemonPanel | undefined; public static readonly viewType = 'pokemonCoding'; private readonly _panel: vscode.WebviewPanel; public static createOrShow( extensionUri: vscode.Uri, pokemonColor: PokemonColor, pokemonType: PokemonType, pokemonSize: PokemonSize, pokemonGeneration: string, pokemonOriginalSpriteSize: number, theme: Theme, themeKind: ColorThemeKind, throwBallWithMouse: boolean, ) { const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined; // If we already have a panel, show it. if (PokemonPanel.currentPanel) { if ( pokemonColor === PokemonPanel.currentPanel.pokemonColor() && pokemonType === PokemonPanel.currentPanel.pokemonType() && pokemonSize === PokemonPanel.currentPanel.pokemonSize() && pokemonGeneration === PokemonPanel.currentPanel.pokemonGeneration() ) { PokemonPanel.currentPanel._panel.reveal(column); return; } else { PokemonPanel.currentPanel.updatePokemonColor(pokemonColor); PokemonPanel.currentPanel.updatePokemonType(pokemonType); PokemonPanel.currentPanel.updatePokemonSize(pokemonSize); PokemonPanel.currentPanel.update(); } } // Otherwise, create a new panel. const panel = vscode.window.createWebviewPanel( PokemonPanel.viewType, vscode.l10n.t('Pokemon Panel'), vscode.ViewColumn.Two, getWebviewOptions(extensionUri), ); PokemonPanel.currentPanel = new PokemonPanel( panel, extensionUri, pokemonColor, pokemonType, pokemonSize, pokemonGeneration, pokemonOriginalSpriteSize, theme, themeKind, throwBallWithMouse, ); } public resetPokemon() { void this.getWebview().postMessage({ command: 'reset-pokemon' }); } public listPokemon() { void this.getWebview().postMessage({ command: 'list-pokemon' }); } public rollCall(): void { void this.getWebview().postMessage({ command: 'roll-call' }); } public deletePokemon(pokemonName: string): void { void this.getWebview().postMessage({ command: 'delete-pokemon', name: pokemonName, }); } public static revive( panel: vscode.WebviewPanel, extensionUri: vscode.Uri, pokemonColor: PokemonColor, pokemonType: PokemonType, pokemonSize: PokemonSize, pokemonGeneration: string, pokemonOriginalSpriteSize: number, theme: Theme, themeKind: ColorThemeKind, throwBallWithMouse: boolean, ) { PokemonPanel.currentPanel = new PokemonPanel( panel, extensionUri, pokemonColor, pokemonType, pokemonSize, pokemonGeneration, pokemonOriginalSpriteSize, theme, themeKind, throwBallWithMouse, ); } private constructor( panel: vscode.WebviewPanel, extensionUri: vscode.Uri, color: PokemonColor, type: PokemonType, size: PokemonSize, generation: string, originalSpriteSize: number, theme: Theme, themeKind: ColorThemeKind, throwBallWithMouse: boolean, ) { super( extensionUri, color, type, size, generation, originalSpriteSize, theme, themeKind, throwBallWithMouse, ); this._panel = panel; // Set the webview's initial html content this._update(); // Listen for when the panel is disposed // This happens when the user closes the panel or when the panel is closed programmatically this._panel.onDidDispose(() => this.dispose(), null, this._disposables); // Update the content based on view changes this._panel.onDidChangeViewState( () => { this.update(); }, null, this._disposables, ); // Handle messages from the webview this._panel.webview.onDidReceiveMessage( handleWebviewMessage, null, this._disposables, ); } public dispose() { PokemonPanel.currentPanel = undefined; // Clean up our resources this._panel.dispose(); while (this._disposables.length) { const x = this._disposables.pop(); if (x) { x.dispose(); } } } public update() { if (this._panel.visible) { this._update(); } } getWebview(): vscode.Webview { return this._panel.webview; } } class PokemonWebviewViewProvider extends PokemonWebviewContainer { public static readonly viewType = 'pokemonView'; private _webviewView?: vscode.WebviewView; private _context: vscode.ExtensionContext; constructor( context: vscode.ExtensionContext, extensionUri: vscode.Uri, color: PokemonColor, type: PokemonType, size: PokemonSize, generation: string, originalSpriteSize: number, theme: Theme, themeKind: ColorThemeKind, throwBallWithMouse: boolean, ) { super( extensionUri, color, type, size, generation, originalSpriteSize, theme, themeKind, throwBallWithMouse, ); this._context = context; } async resolveWebviewView(webviewView: vscode.WebviewView): Promise { this._webviewView = webviewView; webviewView.webview.options = getWebviewOptions(this._extensionUri); webviewView.webview.html = this._getHtmlForWebview(webviewView.webview); webviewView.webview.onDidReceiveMessage( handleWebviewMessage, null, this._disposables, ); const collection = getDefaultPokemonForFreshSession(this._context); if (shouldSpawnInitialCollection(collection)) { await spawnAndPersistCollection(this._context, this, collection); } } update() { this._update(); } getWebview(): vscode.Webview { if (this._webviewView === undefined) { throw new Error( vscode.l10n.t( 'Panel not active, make sure the pokemon view is visible before running this command.', ), ); } else { return this._webviewView.webview; } } } function getNonce() { let text = ''; const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; for (let i = 0; i < 32; i++) { text += possible.charAt(Math.floor(Math.random() * possible.length)); } return text; } async function createPokemonPlayground(context: vscode.ExtensionContext) { const spec = PokemonSpecification.fromConfiguration(); PokemonPanel.createOrShow( context.extensionUri, spec.color, spec.type, spec.size, spec.generation, spec.originalSpriteSize, getConfiguredTheme(), getConfiguredThemeKind(), getThrowWithMouseConfiguration(), ); if (PokemonPanel.currentPanel) { var collection = PokemonSpecification.collectionFromMemento( context, getConfiguredSize(), ); collection.forEach((item) => { PokemonPanel.currentPanel?.spawnPokemon(item); }); await storeCollectionAsMemento(context, collection); } else { var collection = PokemonSpecification.collectionFromMemento( context, getConfiguredSize(), ); collection.push(spec); await storeCollectionAsMemento(context, collection); } } ================================================ FILE: src/panel/base-pokemon-type.ts ================================================ import { POKEMON_DATA } from '../common/pokemon-data'; import { PokemonColor, PokemonExtraSprite, PokemonSize, PokemonSpeed, } from '../common/types'; import { ISequenceTree } from './sequences'; import { States, IState, resolveState, PokemonInstanceState, isStateAboveGround, BallState, ChaseState, HorizontalDirection, FrameResult, IPokemonType, } from './states'; export class InvalidStateError extends Error { fromState: States; pokemonType: string; constructor(fromState: States, pokemonType: string) { super(`Invalid state ${fromState} for pokemon type ${pokemonType}`); this.fromState = fromState; this.pokemonType = pokemonType; } } export abstract class BasePokemonType implements IPokemonType { label: string = 'base'; static count: number = 0; sequence: ISequenceTree = { startingState: States.sitIdle, sequenceStates: [], }; static possibleColors: PokemonColor[]; currentState: IState; currentStateEnum: States; holdState: IState | undefined; holdStateEnum: States | undefined; private el: HTMLImageElement; private collision: HTMLDivElement; private speech: HTMLImageElement; private _left: number; private _bottom: number; pokemonRoot: string; _floor: number; _friend: IPokemonType | undefined; private _name: string; private _baseSpeed: number; private _size: PokemonSize; private _generation: string; private _originalSpriteSize: number; constructor( spriteElement: HTMLImageElement, collisionElement: HTMLDivElement, speechElement: HTMLImageElement, size: PokemonSize, left: number, bottom: number, pokemonRoot: string, floor: number, name: string, speed: number, generation: string, originalSpriteSize: number, ) { this.el = spriteElement; this.collision = collisionElement; this.speech = speechElement; this.pokemonRoot = pokemonRoot; this._floor = floor; this._left = left; this._bottom = bottom; this._originalSpriteSize = originalSpriteSize; this.initSprite(size, left, bottom, originalSpriteSize); this.currentStateEnum = this.sequence.startingState; this.currentState = resolveState(this.currentStateEnum, this); this._name = name; this._size = size; this._baseSpeed = this.randomizeSpeed(speed); this._generation = generation; // Increment the static count of the Pokemon class that the constructor belongs to (this.constructor as typeof BasePokemonType).count += 1; } initSprite( pokemonSize: PokemonSize, left: number, bottom: number, originalSpriteSize: number, ) { const spriteSize = this.calculateSpriteWidth( pokemonSize, originalSpriteSize, ); this.el.style.left = `${left}px`; this.el.style.bottom = `${bottom}px`; this.el.style.width = `${spriteSize}px`; this.el.style.height = `${spriteSize}px`; // Remove 'auto' since it gave issues with sizing this.el.style.maxWidth = 'none'; this.el.style.maxHeight = 'none'; this.collision.style.left = `${left}px`; this.collision.style.bottom = `${bottom}px`; this.collision.style.width = `${spriteSize}px`; this.collision.style.height = `${spriteSize}px`; this.speech.style.left = `${left}px`; this.speech.style.bottom = `${bottom + spriteSize}px`; this.hideSpeechBubble(); } get left(): number { return this._left; } get bottom(): number { return this._bottom; } private repositionAccompanyingElements() { this.collision.style.left = `${this._left}px`; this.collision.style.bottom = `${this._bottom}px`; this.speech.style.left = `${this._left}px`; this.speech.style.bottom = `${ this._bottom + this.calculateSpriteWidth(this._size, this._originalSpriteSize) }px`; } calculateSpriteWidth(size: PokemonSize, originalSpriteSize: number): number { switch (size) { case PokemonSize.nano: return originalSpriteSize; case PokemonSize.small: return originalSpriteSize * 1.5; case PokemonSize.medium: return originalSpriteSize * 2; case PokemonSize.large: return originalSpriteSize * 2.5; default: return originalSpriteSize; } } positionBottom(bottom: number): void { this._bottom = bottom; this.el.style.bottom = `${this._bottom}px`; this.repositionAccompanyingElements(); } positionLeft(left: number): void { this._left = left; this.el.style.left = `${this._left}px`; this.repositionAccompanyingElements(); } get width(): number { return this.el.width; } get floor(): number { return this._floor; } get hello(): string { // return the sound of the name of the animal return ` says hello 👋!`; } getState(): PokemonInstanceState { return { currentStateEnum: this.currentStateEnum }; } get speed(): number { const base = this._baseSpeed ?? 0; switch (this._size) { case PokemonSize.nano: return base * 0.5; // much slower for nano case PokemonSize.small: return base * 0.75; // slower for small case PokemonSize.medium: return base * 1.0; // baseline case PokemonSize.large: return base * 1.25; // slightly faster for large default: return base; } } randomizeSpeed(speed: number): number { const min = speed * 0.7; const max = speed * 1.3; const newSpeed = Math.random() * (max - min) + min; return newSpeed; } get isMoving(): boolean { return this._baseSpeed !== PokemonSpeed.still; } recoverFriend(friend: IPokemonType) { // Recover friends.. this._friend = friend; } recoverState(state: PokemonInstanceState) { // TODO : Resolve a bug where if it was swiping before, it would fail // because holdState is no longer valid. this.currentStateEnum = state.currentStateEnum ?? States.sitIdle; this.currentState = resolveState(this.currentStateEnum, this); if (!isStateAboveGround(this.currentStateEnum)) { // Reset the bottom of the sprite to the floor as the theme // has likely changed. this.positionBottom(this.floor); } } get canSwipe() { return !isStateAboveGround(this.currentStateEnum); } get canChase() { return !isStateAboveGround(this.currentStateEnum) && this.isMoving; } showSpeechBubble(duration: number = 3000, friend: boolean = false) { // Extract the media folder const segments = this.pokemonRoot.split('/'); const basePath = segments.slice(0, segments.length - 3).join('/'); if (friend) { this.speech.src = `${basePath}/heart.png`; } else { this.speech.src = `${basePath}/happy.png`; } this.speech.style.display = 'block'; setTimeout(() => { this.hideSpeechBubble(); }, duration); } hideSpeechBubble() { this.speech.style.display = 'none'; } swipe() { if (this.currentStateEnum === States.swipe) { return; } this.holdState = this.currentState; this.holdStateEnum = this.currentStateEnum; this.currentStateEnum = States.swipe; this.currentState = resolveState(this.currentStateEnum, this); this.showSpeechBubble(); } chase(ballState: BallState, canvas: HTMLCanvasElement) { this.currentStateEnum = States.chase; this.currentState = new ChaseState(this, ballState, canvas); } faceLeft() { this.el.style.transform = 'scaleX(-1)'; } faceRight() { this.el.style.transform = 'scaleX(1)'; } setAnimation(face: string, hasLeftFacingSprite: boolean | undefined) { const validFace = !hasLeftFacingSprite && face === 'walk_left' ? 'walk' : face; if (this.el.src.endsWith(`_${validFace}_8fps.gif`)) { return; } this.el.src = `${this.pokemonRoot}_${validFace}_8fps.gif`; } chooseNextState(fromState: States): States { // Work out next state var possibleNextStates: States[] | undefined = undefined; for (var i = 0; i < this.sequence.sequenceStates.length; i++) { if (this.sequence.sequenceStates[i].state === fromState) { possibleNextStates = this.sequence.sequenceStates[i].possibleNextStates; } } if (!possibleNextStates) { throw new InvalidStateError(fromState, this.label); } // randomly choose the next state const idx = Math.floor(Math.random() * possibleNextStates.length); return possibleNextStates[idx]; } nextFrame() { const hasLeftFacingSprite = POKEMON_DATA[ this.label ]?.extraSprites?.includes(PokemonExtraSprite.leftFacing); if (!hasLeftFacingSprite) { if (this.currentState.horizontalDirection === HorizontalDirection.left) { this.faceLeft(); } else if ( this.currentState.horizontalDirection === HorizontalDirection.right ) { this.faceRight(); } } else { this.faceRight(); } this.setAnimation(this.currentState.spriteLabel, hasLeftFacingSprite); // What's my buddy doing? if ( this.hasFriend && this.currentStateEnum !== States.chaseFriend && this.isMoving ) { if ( this.friend?.isPlaying && !isStateAboveGround(this.currentStateEnum) ) { this.currentState = resolveState(States.chaseFriend, this); this.currentStateEnum = States.chaseFriend; return; } } var frameResult = this.currentState.nextFrame(); if (frameResult === FrameResult.stateComplete) { // If recovering from swipe.. if (this.holdState && this.holdStateEnum) { this.currentState = this.holdState; this.currentStateEnum = this.holdStateEnum; this.holdState = undefined; this.holdStateEnum = undefined; return; } var nextState = this.chooseNextState(this.currentStateEnum); this.currentState = resolveState(nextState, this); this.currentStateEnum = nextState; } else if (frameResult === FrameResult.stateCancel) { if (this.currentStateEnum === States.chase) { var nextState = this.chooseNextState(States.idleWithBall); this.currentState = resolveState(nextState, this); this.currentStateEnum = nextState; } else if (this.currentStateEnum === States.chaseFriend) { var nextState = this.chooseNextState(States.idleWithBall); this.currentState = resolveState(nextState, this); this.currentStateEnum = nextState; } } } get hasFriend(): boolean { return this._friend !== undefined; } get friend(): IPokemonType | undefined { return this._friend; } get name(): string { return this._name; } makeFriendsWith(friend: IPokemonType): boolean { this._friend = friend; console.log(this.name, ": I'm now friends ❤️ with ", friend.name); return true; } get isPlaying(): boolean { return ( this.isMoving && (this.currentStateEnum === States.runRight || this.currentStateEnum === States.runLeft) ); } get emoji(): string { return '🐶'; } } ================================================ FILE: src/panel/main.ts ================================================ // This script will be run within the webview itself import { randomName } from '../common/names'; import { PokemonSize, PokemonColor, PokemonType, Theme, ColorThemeKind, WebviewMessage, } from '../common/types'; import { IPokemonType } from './states'; import { createPokemon, PokemonCollection, PokemonElement, IPokemonCollection, availableColors, InvalidPokemonException, } from './pokemon-collection'; import { PokemonElementState, PokemonPanelState } from './states'; import { getRandomPokemonConfig } from '../common/pokemon-data'; /* This is how the VS Code API can be invoked from the panel */ declare global { interface VscodeStateApi { getState(): PokemonPanelState | undefined; // API is actually Any, but we want it to be typed. setState(state: PokemonPanelState): void; postMessage(message: WebviewMessage): void; } function acquireVsCodeApi(): VscodeStateApi; } export var allPokemon: IPokemonCollection = new PokemonCollection(); var pokemonCounter: number; function normalizePokemonCounter(counter: number | undefined): number { if (counter === undefined || Number.isNaN(counter)) { return 0; } return Math.max(0, counter); } function calculateFloor(size: PokemonSize, theme: Theme): number { switch (theme) { case Theme.forest: switch (size) { case PokemonSize.small: return 30; case PokemonSize.medium: return 40; case PokemonSize.large: return 65; case PokemonSize.nano: default: return 23; } case Theme.castle: switch (size) { case PokemonSize.small: return 60; case PokemonSize.medium: return 80; case PokemonSize.large: return 120; case PokemonSize.nano: default: return 45; } case Theme.beach: switch (size) { case PokemonSize.small: return 60; case PokemonSize.medium: return 80; case PokemonSize.large: return 120; case PokemonSize.nano: default: return 45; } } return 0; } function handleMouseOver(e: MouseEvent) { var el = e.currentTarget as HTMLDivElement; allPokemon.pokemonCollection.forEach((element) => { if (element.collision === el) { if (!element.pokemon.canSwipe) { return; } element.pokemon.swipe(); } }); } function startAnimations( collision: HTMLDivElement, pokemon: IPokemonType, stateApi?: VscodeStateApi, ) { if (!stateApi) { stateApi = acquireVsCodeApi(); } collision.addEventListener('mouseover', handleMouseOver); setInterval(() => { var updates = allPokemon.seekNewFriends(); updates.forEach((message) => { stateApi?.postMessage({ text: message, command: 'info', }); }); pokemon.nextFrame(); saveState(stateApi); }, 100); } function addPokemonToPanel( pokemonType: PokemonType, basePokemonUri: string, gen: string, originalSpriteSize: number, pokemonColor: PokemonColor, pokemonSize: PokemonSize, left: number, bottom: number, floor: number, name: string, stateApi?: VscodeStateApi, incrementCounter: boolean = true, ): PokemonElement { var pokemonSpriteElement: HTMLImageElement = document.createElement('img'); pokemonSpriteElement.className = 'pokemon'; (document.getElementById('pokemonContainer') as HTMLDivElement).appendChild( pokemonSpriteElement, ); var collisionElement: HTMLDivElement = document.createElement('div'); collisionElement.className = 'collision'; (document.getElementById('pokemonContainer') as HTMLDivElement).appendChild( collisionElement, ); var speechBubbleElement: HTMLImageElement = document.createElement('img'); speechBubbleElement.className = `bubble bubble-${pokemonSize} b-${originalSpriteSize}`; speechBubbleElement.src = `${basePokemonUri}/heart.png`; (document.getElementById('pokemonContainer') as HTMLDivElement).appendChild( speechBubbleElement, ); const root = `${basePokemonUri}/${gen}/${pokemonType}/${pokemonColor}`; console.log( 'Creating new pokemon : ', pokemonType, root, pokemonColor, pokemonSize, name, originalSpriteSize, ); try { if (!availableColors(pokemonType).includes(pokemonColor)) { throw new InvalidPokemonException('Invalid color for pokemon type'); } var newPokemon = createPokemon( pokemonType, pokemonSpriteElement, collisionElement, speechBubbleElement, pokemonSize, left, bottom, root, floor, name, gen, originalSpriteSize, ); if (incrementCounter) { pokemonCounter++; } startAnimations(collisionElement, newPokemon, stateApi); } catch (e: unknown) { // Remove elements pokemonSpriteElement.remove(); collisionElement.remove(); speechBubbleElement.remove(); throw e; } pokemonSpriteElement.style.opacity = '0'; const pokeballEl = document.createElement('div'); pokeballEl.classList.add('pokeball-sprite'); // Position pokeball at pokemon location + pokemon center offset pokeballEl.style.left = `${left}px`; pokeballEl.style.bottom = `${bottom}px`; (document.getElementById('pokemonContainer') as HTMLDivElement).appendChild( pokeballEl, ); pokeballEl.offsetHeight; pokeballEl.classList.add('pokeball-open'); // show pokemon earlier while pokeball animation is still running const computed = window.getComputedStyle(pokeballEl); const durationStr = (computed.animationDuration || '0s').split(',')[0].trim(); const durationMs = durationStr.endsWith('ms') ? parseFloat(durationStr) : parseFloat(durationStr) * 1000; const spawnRatio = 0.7; const spawnDelay = Math.max(0, durationMs * spawnRatio); let spawned = false; const showPokemon = () => { if (spawned) { return; } spawned = true; pokemonSpriteElement.classList.add('spawn-pop'); pokemonSpriteElement.style.opacity = '1'; if (pokemonColor === PokemonColor.shiny) { const shinyOverlay = document.createElement('img'); shinyOverlay.src = `${basePokemonUri}/shiny-anim.gif?t=${Date.now()}`; shinyOverlay.className = 'shiny-overlay'; shinyOverlay.style.left = pokemonSpriteElement.style.left; shinyOverlay.style.bottom = pokemonSpriteElement.style.bottom; shinyOverlay.style.width = pokemonSpriteElement.style.width; shinyOverlay.style.height = pokemonSpriteElement.style.height; ( document.getElementById('pokemonContainer') as HTMLDivElement ).appendChild(shinyOverlay); const removeOverlay = () => shinyOverlay.remove(); shinyOverlay.addEventListener('animationend', removeOverlay); setTimeout(removeOverlay, 1500); } saveState(stateApi); }; const spawnTimeout = setTimeout(showPokemon, spawnDelay); pokeballEl.addEventListener('animationend', (e) => { if (e.animationName !== 'pokeball-open') { return; } pokeballEl.remove(); clearTimeout(spawnTimeout); showPokemon(); }); return new PokemonElement( pokemonSpriteElement, collisionElement, speechBubbleElement, newPokemon, pokemonColor, pokemonType, gen, originalSpriteSize, ); } function removePokemonFromPanel( message: { name: string }, stateApi?: VscodeStateApi, ) { if (!stateApi) { stateApi = acquireVsCodeApi(); } // Remove elements var pokemon = allPokemon.locate(message.name); if (!pokemon) { stateApi?.postMessage({ command: 'error', text: `Could not find pokemon ${message.name}`, }); return; } var pokemonSpriteElement = pokemon.el; console.log('Removing pokemon ', message.name); console.log('pokemon:', pokemon); // Remove from collection immediately so rapid deletes of Pokemon don't interfere with each other allPokemon.removeFromCollection(message.name); pokemon.collision.remove(); pokemon.speech.remove(); pokemonCounter = normalizePokemonCounter(pokemonCounter - 1); saveState(stateApi); stateApi?.postMessage({ command: 'info', text: '👋 Removed pokemon ' + message.name, }); // pokemon fade out pokemonSpriteElement.classList.add('fade-out'); const pokeballEl = document.createElement('div'); pokeballEl.classList.add('pokeball-sprite'); pokeballEl.style.left = `${pokemon.pokemon.left}px`; pokeballEl.style.bottom = `${pokemon.pokemon.bottom}px`; const container = document.getElementById( 'pokemonContainer', ) as HTMLDivElement; container.appendChild(pokeballEl); pokeballEl.offsetHeight; pokeballEl.classList.add('pokeball-close'); pokemonSpriteElement.addEventListener( 'animationend', (e) => { if (e.animationName !== 'pokemon-fade-out') { return; } pokemonSpriteElement.remove(); }, { once: true }, ); pokeballEl.addEventListener( 'animationend', (e) => { if (e.animationName !== 'pokeball-close') { return; } pokeballEl.remove(); }, { once: true }, ); } export function saveState(stateApi?: VscodeStateApi) { if (!stateApi) { stateApi = acquireVsCodeApi(); } var state = new PokemonPanelState(); state.pokemonStates = []; allPokemon.pokemonCollection.forEach((pokemonItem) => { state.pokemonStates?.push({ pokemonName: pokemonItem.pokemon.name, pokemonColor: pokemonItem.color, pokemonType: pokemonItem.type, pokemonState: pokemonItem.pokemon.getState(), pokemonGeneration: pokemonItem.generation, originalSpriteSize: pokemonItem.originalSpriteSize, pokemonFriend: pokemonItem.pokemon.friend?.name ?? undefined, elLeft: pokemonItem.el.style.left, elBottom: pokemonItem.el.style.bottom, }); }); state.pokemonCounter = normalizePokemonCounter(pokemonCounter); stateApi?.setState(state); } function recoverState( basePokemonUri: string, gen: string, pokemonSize: PokemonSize, floor: number, stateApi?: VscodeStateApi, ) { if (!stateApi) { stateApi = acquireVsCodeApi(); } var state = stateApi?.getState(); if (!state) { pokemonCounter = 0; } else { pokemonCounter = normalizePokemonCounter(state.pokemonCounter); } var recoveryMap: Map = new Map(); console.log( 'recoverState: saved pokemon count =', state?.pokemonStates?.length ?? 0, ); state?.pokemonStates?.forEach((p) => { console.log('Recovering pokemon ', p.pokemonType, p.pokemonName); try { console.log('Adding pokemon to panel for recovery'); var newPokemon = addPokemonToPanel( p.pokemonType ?? 'bulbasaur', basePokemonUri, p.pokemonGeneration ?? 'gen1', p.originalSpriteSize ?? 32, p.pokemonColor ?? PokemonColor.default, pokemonSize, parseInt(p.elLeft ?? '0'), parseInt(p.elBottom ?? '0'), floor, p.pokemonName ?? randomName(), stateApi, false, ); allPokemon.push(newPokemon); recoveryMap.set(newPokemon.pokemon, p); } catch (InvalidPokemonException) { console.log( 'State had invalid pokemon (' + p.pokemonType + '), discarding.', ); } }); recoveryMap.forEach((state, pokemon) => { // Recover previous state. if (state.pokemonState !== undefined) { pokemon.recoverState(state.pokemonState); } // Resolve friend relationships var friend = undefined; if (state.pokemonFriend) { friend = allPokemon.locate(state.pokemonFriend); if (friend) { pokemon.recoverFriend(friend.pokemon); } } }); } function randomStartPosition(): number { return Math.floor(Math.random() * (window.innerWidth * 0.7)); } let canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D; function initCanvas() { canvas = document.getElementById('pokemonCanvas') as HTMLCanvasElement; if (!canvas) { console.log('Canvas not ready'); return; } ctx = canvas.getContext('2d') as CanvasRenderingContext2D; if (!ctx) { console.log('Canvas context not ready'); return; } ctx.canvas.width = window.innerWidth; ctx.canvas.height = window.innerHeight; } // It cannot access the main VS Code APIs directly. export function pokemonPanelApp( basePokemonUri: string, theme: Theme, themeKind: ColorThemeKind, pokemonColor: PokemonColor, pokemonSize: PokemonSize, pokemonType: PokemonType, throwBallWithMouse: boolean, gen: string, originalSpriteSize: number, stateApi?: VscodeStateApi, ) { var floor = 0; if (!stateApi) { stateApi = acquireVsCodeApi(); } // Apply Theme backgrounds const foregroundEl = document.getElementById('foreground'); if (theme !== Theme.none) { var _themeKind = ''; switch (themeKind) { case ColorThemeKind.dark: _themeKind = 'dark'; break; case ColorThemeKind.light: _themeKind = 'light'; break; case ColorThemeKind.highContrast: default: _themeKind = 'light'; break; } document.body.style.backgroundImage = `url('${basePokemonUri}/backgrounds/${theme}/background-${_themeKind}-${pokemonSize}.png')`; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion foregroundEl!.style.backgroundImage = `url('${basePokemonUri}/backgrounds/${theme}/foreground-${_themeKind}-${pokemonSize}.png')`; floor = calculateFloor(pokemonSize, theme); // Themes have pokemonCollection at a specified height from the ground } else { document.body.style.backgroundImage = ''; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion foregroundEl!.style.backgroundImage = ''; } console.log( 'Starting pokemon session', pokemonColor, basePokemonUri, pokemonType, throwBallWithMouse, ); // New session var state = stateApi?.getState(); const hasRecoverableState = state !== undefined && Array.isArray(state.pokemonStates) && state.pokemonStates.length > 0; if (hasRecoverableState) { console.log('Recovering state - ', state); recoverState(basePokemonUri, gen, pokemonSize, floor, stateApi); } else { console.log('No recoverable pokemon state, starting an empty session.'); pokemonCounter = normalizePokemonCounter(state?.pokemonCounter); saveState(stateApi); } initCanvas(); // Handle messages sent from the extension to the webview window.addEventListener('message', (event): void => { const message = event.data; // The json data that the extension sent console.log('Received message in panel:', message); switch (message.command) { case 'spawn-pokemon': console.log('adding pokemon to panel from message', message); allPokemon.push( addPokemonToPanel( message.type, basePokemonUri, message.generation, message.originalSpriteSize, message.color, pokemonSize, randomStartPosition(), floor, floor, message.name ?? randomName(), stateApi, ), ); saveState(stateApi); break; case 'spawn-random-pokemon': var [randomPokemonType, randomPokemonConfig] = getRandomPokemonConfig(); console.log('adding random pokemon to panel from message'); allPokemon.push( addPokemonToPanel( randomPokemonType, basePokemonUri, randomPokemonConfig.generation.toString(), randomPokemonConfig.originalSpriteSize ?? 32, PokemonColor.default, pokemonSize, randomStartPosition(), floor, floor, randomName(), stateApi, ), ); saveState(stateApi); break; case 'list-pokemon': var pokemonCollection = allPokemon.pokemonCollection; stateApi?.postMessage({ command: 'list-pokemon', text: pokemonCollection .map( (pokemon) => `${pokemon.type},${pokemon.pokemon.name},${pokemon.color}`, ) .join('\n'), }); break; case 'roll-call': var pokemonCollection = allPokemon.pokemonCollection; // go through every single // pokemon and then print out their name pokemonCollection.forEach((pokemon) => { stateApi?.postMessage({ command: 'info', text: `${pokemon.pokemon.emoji} ${pokemon.pokemon.name} (${pokemon.color} ${pokemon.type}): ${pokemon.pokemon.hello}`, }); }); break; case 'delete-pokemon': removePokemonFromPanel(message, stateApi); break; case 'reset-pokemon': var pokemonToRemove = [...allPokemon.pokemonCollection]; pokemonToRemove.forEach((pokemon) => { removePokemonFromPanel({ name: pokemon.pokemon.name }, stateApi); }); // Wait for animations to complete before resetting setTimeout(() => { allPokemon.reset(); pokemonCounter = 0; saveState(stateApi); }, 500); break; case 'pause-pokemon': pokemonCounter = 1; saveState(stateApi); break; } }); } window.addEventListener('resize', function () { initCanvas(); }); ================================================ FILE: src/panel/pokemon-collection.ts ================================================ import { PokemonColor, PokemonSize, PokemonSpeed, PokemonType, } from '../common/types'; import { Pokemon } from './pokemon'; import { IPokemonType } from './states'; export class PokemonElement { el: HTMLImageElement; collision: HTMLDivElement; speech: HTMLDivElement; pokemon: IPokemonType; color: PokemonColor; type: PokemonType; generation: string; originalSpriteSize: number; remove() { this.el.remove(); this.collision.remove(); this.speech.remove(); this.color = PokemonColor.null; } constructor( el: HTMLImageElement, collision: HTMLDivElement, speech: HTMLDivElement, pokemon: IPokemonType, color: PokemonColor, type: PokemonType, generation: string, originalSpriteSize: number, ) { this.el = el; this.collision = collision; this.speech = speech; this.pokemon = pokemon; this.color = color; this.type = type; this.generation = generation; this.originalSpriteSize = originalSpriteSize; } } export interface IPokemonCollection { pokemonCollection: Array; push(pokemon: PokemonElement): void; reset(): void; seekNewFriends(): string[]; locate(name: string): PokemonElement | undefined; remove(name: string): void; removeFromCollection(name: string): void; } export class PokemonCollection implements IPokemonCollection { private _pokemonCollection: Array; constructor() { this._pokemonCollection = new Array(0); } public get pokemonCollection() { return this._pokemonCollection; } push(pokemon: PokemonElement) { this._pokemonCollection.push(pokemon); } reset() { this._pokemonCollection.forEach((pokemon) => { pokemon.remove(); }); this._pokemonCollection = []; } locate(name: string): PokemonElement | undefined { return this._pokemonCollection.find((collection) => { return collection.pokemon.name === name; }); } remove(name: string): any { const idx = this._pokemonCollection.findIndex( (pokemon) => pokemon.pokemon.name === name, ); if (idx === -1) { return; } this._pokemonCollection[idx].remove(); this._pokemonCollection.splice(idx, 1); } removeFromCollection(name: string): void { const idx = this._pokemonCollection.findIndex( (pokemon) => pokemon.pokemon.name === name, ); if (idx === -1) { return; } this._pokemonCollection.splice(idx, 1); } seekNewFriends(): string[] { if (this._pokemonCollection.length <= 1) { return []; } // You can't be friends with yourself. var messages = new Array(0); this._pokemonCollection.forEach((pokemonInCollection) => { if (pokemonInCollection.pokemon.hasFriend) { return; } // I already have a friend! this._pokemonCollection.forEach((potentialFriend) => { if (potentialFriend.pokemon.hasFriend) { return; } // Already has a friend. sorry. if (!potentialFriend.pokemon.canChase) { return; } // Pokemon is busy doing something else. if ( potentialFriend.pokemon.left > pokemonInCollection.pokemon.left && potentialFriend.pokemon.left < pokemonInCollection.pokemon.left + pokemonInCollection.pokemon.width ) { // We found a possible new friend.. console.log( pokemonInCollection.pokemon.name, ' wants to be friends with ', potentialFriend.pokemon.name, '.', ); if ( pokemonInCollection.pokemon.makeFriendsWith(potentialFriend.pokemon) ) { potentialFriend.pokemon.showSpeechBubble(2000, true); pokemonInCollection.pokemon.showSpeechBubble(2000, true); } } }); }); return messages; } } export class InvalidPokemonException { message?: string; constructor(message?: string) { this.message = message; } } export function createPokemon( pokemonType: string, el: HTMLImageElement, collision: HTMLDivElement, speech: HTMLImageElement, size: PokemonSize, left: number, bottom: number, pokemonRoot: string, floor: number, name: string, generation: string, originalSpriteSize: number, ): IPokemonType { if (!name) { throw new InvalidPokemonException('name is undefined'); } try { return new Pokemon( pokemonType, el, collision, speech, size, left, bottom, pokemonRoot, floor, name, PokemonSpeed.normal, generation, originalSpriteSize, ); } catch (error) { throw new InvalidPokemonException(`Invalid Pokemon type: ${pokemonType}`); } } export function availableColors(pokemonType: PokemonType): PokemonColor[] { const pokemon = Pokemon.getPokemonData(pokemonType); return pokemon ? pokemon.possibleColors : [PokemonColor.default]; } export function normalizeColor( pokemonColor: PokemonColor, pokemonType: PokemonType, ): PokemonColor { const colors = availableColors(pokemonType); return colors.includes(pokemonColor) ? pokemonColor : colors[0]; } ================================================ FILE: src/panel/pokemon.ts ================================================ import { POKEMON_DATA } from '../common/pokemon-data'; import { PokemonColor, PokemonConfig, PokemonGeneration, PokemonSize, } from '../common/types'; import { BasePokemonType } from './base-pokemon-type'; import { States } from './states'; export class Pokemon extends BasePokemonType { private config: PokemonConfig; constructor( pokemonType: string, spriteElement: HTMLImageElement, collisionElement: HTMLDivElement, speechElement: HTMLImageElement, size: PokemonSize, left: number, bottom: number, pokemonRoot: string, floor: number, name: string, speed: number, generation: string, originalSpriteSize: number, ) { super( spriteElement, collisionElement, speechElement, size, left, bottom, pokemonRoot, floor, name, speed, generation, originalSpriteSize, ); this.config = POKEMON_DATA[pokemonType] || POKEMON_DATA.bulbasaur; this.label = pokemonType; } static possibleColors = [PokemonColor.default]; sequence = { startingState: States.sitIdle, sequenceStates: [ { state: States.sitIdle, possibleNextStates: [States.walkLeft, States.walkRight], }, { state: States.walkLeft, possibleNextStates: [States.sitIdle, States.walkRight], }, { state: States.walkRight, possibleNextStates: [States.sitIdle, States.walkLeft], }, { state: States.swipe, possibleNextStates: [States.sitIdle], }, ], }; get generation(): PokemonGeneration { return this.config.generation; } get pokedexNumber(): number { return this.config.id; } showSpeechBubble(duration: number = 3000, friend: boolean) { super.showSpeechBubble(duration, friend); } static getPokemonData(type: string): PokemonConfig | undefined { return POKEMON_DATA[type]; } } export const POKEMON_NAMES: ReadonlyArray = [ 'Bella', 'Charlie', 'Molly', 'Coco', 'Ruby', 'Oscar', 'Lucy', 'Bailey', 'Milo', 'Daisy', 'Archie', 'Ollie', 'Rosie', 'Lola', 'Frankie', 'Roxy', 'Poppy', 'Luna', 'Jack', 'Millie', 'Teddy', 'Cooper', 'Bear', 'Rocky', 'Alfie', 'Hugo', 'Bonnie', 'Pepper', 'Lily', 'Tilly', 'Leo', 'Maggie', 'George', 'Mia', 'Marley', 'Harley', 'Chloe', 'Lulu', 'Missy', 'Jasper', 'Billy', 'Nala', 'Monty', 'Ziggy', 'Winston', 'Zeus', 'Zoe', 'Stella', 'Sasha', 'Rusty', 'Gus', 'Baxter', 'Dexter', 'Willow', 'Barney', 'Bruno', 'Penny', 'Honey', 'Milly', 'Murphy', 'Simba', 'Holly', 'Benji', 'Henry', 'Lilly', 'Pippa', 'Shadow', 'Sam', 'Lucky', 'Ellie', 'Duke', 'Jessie', 'Cookie', 'Harvey', 'Bruce', 'Jax', 'Rex', 'Louie', 'Jet', 'Banjo', ]; ================================================ FILE: src/panel/sequences.ts ================================================ import { States } from './states'; export interface ISequenceNode { state: States; possibleNextStates: States[]; } export interface ISequenceTree { startingState: States; sequenceStates: ISequenceNode[]; } ================================================ FILE: src/panel/states.ts ================================================ import { PokemonColor, PokemonType } from '../common/types'; export interface IPokemonType { nextFrame(): void; // Special methods for actions canSwipe: boolean; canChase: boolean; swipe(): void; chase(ballState: BallState, canvas: HTMLCanvasElement): void; speed: number; isMoving: boolean; hello: string; // State API getState(): PokemonInstanceState; recoverState(state: PokemonInstanceState): void; recoverFriend(friend: IPokemonType): void; // Positioning bottom: number; left: number; positionBottom(bottom: number): void; positionLeft(left: number): void; width: number; floor: number; // Friends API name: string; emoji: string; hasFriend: boolean; friend: IPokemonType | undefined; makeFriendsWith(friend: IPokemonType): boolean; isPlaying: boolean; showSpeechBubble(duration: number, friend: boolean): void; } export class PokemonInstanceState { currentStateEnum: States | undefined; } export class PokemonElementState { pokemonState: PokemonInstanceState | undefined; pokemonGeneration: string | undefined; originalSpriteSize: number | undefined; pokemonType: PokemonType | undefined; pokemonColor: PokemonColor | undefined; elLeft: string | undefined; elBottom: string | undefined; pokemonName: string | undefined; pokemonFriend: string | undefined; } export class PokemonPanelState { pokemonStates: Array | undefined; pokemonCounter: number | undefined; } export enum HorizontalDirection { left, right, natural, // No change to current direction } export const enum States { sitIdle = 'sit-idle', walkRight = 'walk-right', walkLeft = 'walk-left', runRight = 'run-right', runLeft = 'run-left', lie = 'lie', wallHangLeft = 'wall-hang-left', climbWallLeft = 'climb-wall-left', jumpDownLeft = 'jump-down-left', land = 'land', swipe = 'swipe', idleWithBall = 'idle-with-ball', chase = 'chase', chaseFriend = 'chase-friend', standRight = 'stand-right', standLeft = 'stand-left', } export enum FrameResult { stateContinue, stateComplete, // Special states stateCancel, } export class BallState { cx: number; cy: number; vx: number; vy: number; paused: boolean; constructor(cx: number, cy: number, vx: number, vy: number) { this.cx = cx; this.cy = cy; this.vx = vx; this.vy = vy; this.paused = false; } } export function isStateAboveGround(state: States): boolean { return ( state === States.climbWallLeft || state === States.jumpDownLeft || state === States.land || state === States.wallHangLeft ); } export function resolveState(state: string, pokemon: IPokemonType): IState { switch (state) { case States.sitIdle: return new SitIdleState(pokemon); case States.walkRight: return new WalkRightState(pokemon); case States.walkLeft: return new WalkLeftState(pokemon); case States.runRight: return new RunRightState(pokemon); case States.runLeft: return new RunLeftState(pokemon); case States.lie: return new LieState(pokemon); case States.wallHangLeft: return new WallHangLeftState(pokemon); case States.climbWallLeft: return new ClimbWallLeftState(pokemon); case States.jumpDownLeft: return new JumpDownLeftState(pokemon); case States.land: return new LandState(pokemon); case States.swipe: return new SwipeState(pokemon); case States.idleWithBall: return new IdleWithBallState(pokemon); case States.chaseFriend: return new ChaseFriendState(pokemon); case States.standRight: return new StandRightState(pokemon); case States.standLeft: return new StandLeftState(pokemon); } return new SitIdleState(pokemon); } export interface IState { label: string; spriteLabel: string; horizontalDirection: HorizontalDirection; pokemon: IPokemonType; nextFrame(): FrameResult; } class AbstractStaticState implements IState { label = States.sitIdle; idleCounter: number; spriteLabel = 'idle'; holdTime = 50; pokemon: IPokemonType; horizontalDirection = HorizontalDirection.left; constructor(pokemon: IPokemonType) { this.idleCounter = 0; this.pokemon = pokemon; } nextFrame(): FrameResult { this.idleCounter++; if (this.idleCounter > this.holdTime) { return FrameResult.stateComplete; } return FrameResult.stateContinue; } } export class SitIdleState extends AbstractStaticState { label = States.sitIdle; spriteLabel = 'idle'; horizontalDirection = HorizontalDirection.right; holdTime = 50; } export class LieState extends AbstractStaticState { label = States.lie; spriteLabel = 'lie'; horizontalDirection = HorizontalDirection.right; holdTime = 50; } export class WallHangLeftState extends AbstractStaticState { label = States.wallHangLeft; spriteLabel = 'wallgrab'; horizontalDirection = HorizontalDirection.left; holdTime = 50; } export class LandState extends AbstractStaticState { label = States.land; spriteLabel = 'land'; horizontalDirection = HorizontalDirection.left; holdTime = 10; } export class SwipeState extends AbstractStaticState { label = States.swipe; spriteLabel = 'idle'; // use base idle sprite horizontalDirection = HorizontalDirection.natural; holdTime = 15; } export class IdleWithBallState extends AbstractStaticState { label = States.idleWithBall; spriteLabel = 'with_ball'; horizontalDirection = HorizontalDirection.left; holdTime = 30; } export class WalkRightState implements IState { label = States.walkRight; pokemon: IPokemonType; spriteLabel = 'walk'; horizontalDirection = HorizontalDirection.right; leftBoundary: number; speedMultiplier = 1; idleCounter: number; holdTime = 60; constructor(pokemon: IPokemonType) { this.leftBoundary = Math.floor(window.innerWidth * 0.95); this.pokemon = pokemon; this.idleCounter = 0; } nextFrame(): FrameResult { this.idleCounter++; this.pokemon.positionLeft( this.pokemon.left + this.pokemon.speed * this.speedMultiplier, ); // Random chance to stop in the middle if (this.pokemon.isMoving && Math.random() < 0.01) { return FrameResult.stateComplete; } if ( this.pokemon.isMoving && this.pokemon.left >= this.leftBoundary - this.pokemon.width ) { return FrameResult.stateComplete; } else if (!this.pokemon.isMoving && this.idleCounter > this.holdTime) { return FrameResult.stateComplete; } return FrameResult.stateContinue; } } export class WalkLeftState implements IState { label = States.walkLeft; spriteLabel = 'walk_left'; horizontalDirection = HorizontalDirection.left; pokemon: IPokemonType; speedMultiplier = 1; idleCounter: number; holdTime = 60; constructor(pokemon: IPokemonType) { this.pokemon = pokemon; this.idleCounter = 0; } nextFrame(): FrameResult { this.idleCounter++; this.pokemon.positionLeft( this.pokemon.left - this.pokemon.speed * this.speedMultiplier, ); // Random chance to stop in the middle if (this.pokemon.isMoving && Math.random() < 0.01) { return FrameResult.stateComplete; } if (this.pokemon.isMoving && this.pokemon.left <= 0) { return FrameResult.stateComplete; } else if (!this.pokemon.isMoving && this.idleCounter > this.holdTime) { return FrameResult.stateComplete; } return FrameResult.stateContinue; } } export class RunRightState extends WalkRightState { label = States.runRight; spriteLabel = 'walk_fast'; speedMultiplier = 1.6; holdTime = 130; } export class RunLeftState extends WalkLeftState { label = States.runLeft; spriteLabel = 'walk_fast'; speedMultiplier = 1.6; holdTime = 130; } export class ChaseState implements IState { label = States.chase; spriteLabel = 'run'; horizontalDirection = HorizontalDirection.left; ballState: BallState; canvas: HTMLCanvasElement; pokemon: IPokemonType; constructor( pokemon: IPokemonType, ballState: BallState, canvas: HTMLCanvasElement, ) { this.pokemon = pokemon; this.ballState = ballState; this.canvas = canvas; } nextFrame(): FrameResult { if (this.ballState.paused) { return FrameResult.stateCancel; // Ball is already caught } if (this.pokemon.left > this.ballState.cx) { this.horizontalDirection = HorizontalDirection.left; this.pokemon.positionLeft(this.pokemon.left - this.pokemon.speed); } else { this.horizontalDirection = HorizontalDirection.right; this.pokemon.positionLeft(this.pokemon.left + this.pokemon.speed); } if ( this.canvas.height - this.ballState.cy < this.pokemon.width + this.pokemon.floor && this.ballState.cx < this.pokemon.left && this.pokemon.left < this.ballState.cx + 15 ) { // hide ball this.canvas.style.display = 'none'; this.ballState.paused = true; return FrameResult.stateComplete; } return FrameResult.stateContinue; } } export class ChaseFriendState implements IState { label = States.chaseFriend; spriteLabel = 'run'; horizontalDirection = HorizontalDirection.left; pokemon: IPokemonType; constructor(pokemon: IPokemonType) { this.pokemon = pokemon; } nextFrame(): FrameResult { if (!this.pokemon.hasFriend || !this.pokemon.friend?.isPlaying) { return FrameResult.stateCancel; // Friend is no longer playing. } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (this.pokemon.left > this.pokemon.friend!.left) { this.horizontalDirection = HorizontalDirection.left; this.pokemon.positionLeft(this.pokemon.left - this.pokemon.speed); } else { this.horizontalDirection = HorizontalDirection.right; this.pokemon.positionLeft(this.pokemon.left + this.pokemon.speed); } return FrameResult.stateContinue; } } export class ClimbWallLeftState implements IState { label = States.climbWallLeft; spriteLabel = 'wallclimb'; horizontalDirection = HorizontalDirection.left; pokemon: IPokemonType; constructor(pokemon: IPokemonType) { this.pokemon = pokemon; } nextFrame(): FrameResult { this.pokemon.positionBottom(this.pokemon.bottom + 1); if (this.pokemon.bottom >= 100) { return FrameResult.stateComplete; } return FrameResult.stateContinue; } } export class JumpDownLeftState implements IState { label = States.jumpDownLeft; spriteLabel = 'fall_from_grab'; horizontalDirection = HorizontalDirection.right; pokemon: IPokemonType; constructor(pokemon: IPokemonType) { this.pokemon = pokemon; } nextFrame(): FrameResult { this.pokemon.positionBottom(this.pokemon.bottom - 5); if (this.pokemon.bottom <= this.pokemon.floor) { this.pokemon.positionBottom(this.pokemon.floor); return FrameResult.stateComplete; } return FrameResult.stateContinue; } } export class StandRightState extends AbstractStaticState { label = States.standRight; spriteLabel = 'stand'; horizontalDirection = HorizontalDirection.right; holdTime = 60; } export class StandLeftState extends AbstractStaticState { label = States.standRight; spriteLabel = 'stand'; horizontalDirection = HorizontalDirection.left; holdTime = 60; } ================================================ FILE: src/test/gifs.ts ================================================ import * as fs from 'fs'; import { PokemonColor } from '../common/types'; import { getAllPokemon, POKEMON_DATA } from '../common/pokemon-data'; const defaultPokemonConfig = { colors: [PokemonColor.default], states: ['idle', 'walk'], }; const allPokemon = getAllPokemon().reduce( (acc, pokemon) => ({ ...acc, [pokemon]: defaultPokemonConfig, }), {} as { [key: string]: { colors: string[]; states: string[] } }, ); function checkGifFilenames(folder: string) { for (const pokemon in allPokemon) { const allowedColors = allPokemon[pokemon].colors; const allowedStates = allPokemon[pokemon].states; if (!allowedColors) { console.error(`No colors found for pokemon "${pokemon}"`); return; } // Get the generation number from POKEMON_DATA const generation = POKEMON_DATA[pokemon]?.generation || 1; const genFolder = `gen${generation}`; allowedColors.forEach((color) => { allowedStates.forEach((state) => { const filename = `${color}_${state}_8fps.gif`; const filePath = `${folder}/${genFolder}/${pokemon}/${filename}`; if (!fs.existsSync(filePath)) { // \x1b[31m is the ANSI escape code for red, and \x1b[0m resets the color back to the terminal's default. console.error(`\x1b[31mFile "${filePath}" does not exist.\x1b[0m`); return false; } else { console.log(`File "${filePath}" exists.`); } }); }); } } const mediaFolder = './media'; checkGifFilenames(mediaFolder); ================================================ FILE: src/test/package.json ================================================ { "name": "vscode-pokemon-test", "type": "module" } ================================================ FILE: src/test/runTest.js ================================================ import * as path from 'path'; import { runTests } from 'vscode-test'; async function main() { try { // The folder containing the Extension Manifest package.json // Passed to `--extensionDevelopmentPath` const extensionDevelopmentPath = path.resolve(__dirname, '../../'); // The path to test runner // Passed to --extensionTestsPath const extensionTestsPath = path.resolve(__dirname, './suite/index'); // Download VS Code, unzip it and run the integration test await runTests({ extensionDevelopmentPath, extensionTestsPath }); } catch (err) { console.error('Failed to run tests'); process.exit(1); } } main(); ================================================ FILE: src/test/runTest.ts ================================================ import * as path from 'path'; import { runTests } from 'vscode-test'; async function main() { try { // The folder containing the Extension Manifest package.json // Passed to `--extensionDevelopmentPath` const extensionDevelopmentPath = path.resolve(__dirname, '../../'); // The path to test runner // Passed to --extensionTestsPath const extensionTestsPath = path.resolve(__dirname, './suite/index'); // Download VS Code, unzip it and run the integration test await runTests({ extensionDevelopmentPath, extensionTestsPath }); } catch (err) { console.error('Failed to run tests'); process.exit(1); } } void main(); ================================================ FILE: src/test/suite/index.js ================================================ import * as path from 'path'; import * as Mocha from 'mocha'; import * as glob from 'glob'; export function run() { // Create the mocha test const mocha = new Mocha({ ui: 'tdd', color: true, require: ['ts-node/register', 'source-map-support/register'], recursive: true, }); const testsRoot = path.resolve(__dirname, '..'); return new Promise((c, e) => { glob('**/**.test.js', { cwd: testsRoot }, (err, files) => { if (err) { return e(err); } // Add files to the test suite files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))); try { // Run the mocha test mocha.run((failures) => { if (failures > 0) { e(new Error(`${failures} tests failed.`)); } else { c(); } }); } catch (err) { console.error(err); e(err); } }); }); } ================================================ FILE: src/test/suite/index.ts ================================================ import * as path from 'path'; import * as Mocha from 'mocha'; import * as glob from 'glob'; import { join } from 'path'; function setupCoverage() { const NYC = require('nyc'); const nyc = new NYC({ cwd: join(__dirname, '..', '..', '..'), exclude: ['**/test/**', '.vscode-test/**'], reporter: ['text', 'html', 'lcov'], all: true, instrument: true, hookRequire: true, hookRunInContext: true, hookRunInThisContext: true, }); nyc.reset(); nyc.wrap(); return nyc; } export async function run(): Promise { const nyc = process.env.COVERAGE ? setupCoverage() : null; // Create the mocha test const mocha = new Mocha({ ui: 'tdd', color: true, require: [ 'ts-node/register', 'source-map-support/register', 'jsdom-global/register', ], }); const testsRoot = path.resolve(__dirname, '..'); return new Promise((c, e) => { glob('**/**.test.js', { cwd: testsRoot }, async (err, files) => { if (err) { return e(err); } // Add files to the test suite files.forEach((f) => mocha.addFile(path.resolve(testsRoot, f))); try { // Run the mocha test mocha.run((failures) => { if (failures > 0) { e(new Error(`${failures} tests failed.`)); } else { c(); } }); } catch (err) { console.error(err); e(err); } finally { if (nyc) { nyc.writeCoverageFile(); await nyc.report(); } } }); }); } ================================================ FILE: src/test/suite/panel.test.ts ================================================ function mockPanelWindow() { const html = '
'; var jsdom = require('jsdom'); var document = new jsdom.JSDOM(html); var window = document.window; global.document = window.document; global.window = window; window.console = global.console; } mockPanelWindow(); ================================================ FILE: tsconfig.extension.json ================================================ { "compilerOptions": { "module": "commonjs", "target": "esnext", "outDir": "out", "lib": [ "es6" ], "sourceMap": true, "rootDirs": ["extension", "common"], "strict": true /* enable all strict type-checking options */ /* Additional Checks */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ }, "exclude": [ "node_modules", ".vscode-test", "src/panel", "src/test" ] } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { "noImplicitAny": true, "strictNullChecks": true, "outDir": "./.build-out", "lib": ["es2016", "dom"], "target": "esnext" }, "include": ["src"] } ================================================ FILE: tsconfig.panel.json ================================================ { "compilerOptions": { "module": "commonjs", "target": "esnext", "outDir": "./build", "lib": [ "es6", "DOM" ], "sourceMap": true, "rootDirs": ["panel", "common"], "strict": true /* enable all strict type-checking options */ /* Additional Checks */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ }, "exclude": [ "node_modules", ".vscode-test", "src/extension", "src/test" ] } ================================================ FILE: tsconfig.test.json ================================================ { "compilerOptions": { "module": "commonjs", "target": "esnext", "outDir": "out", "lib": ["es6", "DOM"], "sourceMap": true, "rootDirs": ["panel", "common", "test", "extension"], "strict": true /* enable all strict type-checking options */ /* Additional Checks */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ }, "exclude": ["node_modules"] } ================================================ FILE: tsconfig.web.json ================================================ { "compilerOptions": { "module": "commonjs", "target": "es2020", "outDir": "dist", "lib": ["es6", "WebWorker"], "sourceMap": true, "rootDirs": ["panel", "common"], "strict": true /* enable all strict type-checking options */ /* Additional Checks */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ }, "exclude": [ "node_modules", ".vscode-test-web", "src/extension", "src/test", "src/panel" ] } ================================================ FILE: webpack.config.js ================================================ //webpack.config.js const path = require('path'); const webpack = require('webpack'); var removeSourceMapUrlWebpackPlugin = require('@rbarilani/remove-source-map-url-webpack-plugin'); const desktopConfig = { mode: "development", devtool: "inline-source-map", entry: { main: "./src/panel/main.ts", }, output: { path: path.resolve(__dirname, './media'), filename: "[name]-bundle.js", // <--- Will be compiled to this single file library: { name: 'pokemonApp', type: 'global' } }, plugins: [ new removeSourceMapUrlWebpackPlugin({ test: /main-bundle\.js$/ }) ], resolve: { extensions: [".ts", ".tsx", ".js"], }, module: { rules: [{ test: /\.ts$/, exclude: /node_modules/, use: [ { loader: 'ts-loader', options: { configFile: 'tsconfig.panel.json' } }, ], }] }, }; const webExtensionConfig = { mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production') target: 'webworker', // extensions run in a webworker context entry: { extension: './src/extension/extension.ts', // source of the web extension main file // 'test/suite/index': './src/web/test/suite/index.ts', // source of the web extension test runner }, output: { filename: '[name]-web.js', path: path.join(__dirname, './dist/web'), libraryTarget: 'commonjs', }, resolve: { mainFields: ['browser', 'module', 'main'], // look for `browser` entry point in imported node modules extensions: ['.ts', '.js'], // support ts-files and js-files alias: { // provides alternate implementation for node module and source files }, fallback: { // Webpack 5 no longer polyfills Node.js core modules automatically. // see https://webpack.js.org/configuration/resolve/#resolvefallback // for the list of Node.js core module polyfills. "assert": require.resolve('assert'), "path": require.resolve("path-browserify"), "fs": false, }, }, module: { rules: [ { test: /\.ts$/, exclude: /node_modules/, use: [ { loader: 'ts-loader', options: { configFile: 'tsconfig.web.json' } }, ], }, ], }, plugins: [ new webpack.ProvidePlugin({ process: 'process/browser', // provide a shim for the global `process` variable }), ], externals: { vscode: 'commonjs vscode', // ignored because it doesn't exist }, performance: { hints: false, }, devtool: 'nosources-source-map', // create a source map that points to the original source file }; module.exports = [desktopConfig, webExtensionConfig];