diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 70dc2bfa502..e40b18eb69b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,8 +1,12 @@ -name: Deploy +name: Deploy Main on: - push: {} - pull_request: {} + push: + branches: + - main + pull_request: + branches: + - main jobs: deploy: @@ -22,7 +26,7 @@ jobs: env: NODE_ENV: production - name: Set up SSH - if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch + if: github.event_name == 'push' && github.ref_name == 'main' run: | mkdir ~/.ssh echo "${{ secrets.SSH_PUBLIC_KEY }}" > ~/.ssh/id_ed25519.pub @@ -30,12 +34,12 @@ jobs: chmod 600 ~/.ssh/* ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts - name: Deploy build on server - if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch + if: github.event_name == 'push' && github.ref_name == 'main' run: | rsync --del --no-times --checksum -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }} ssh -t ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/prmanifest --inpath ${{ secrets.DESTINATION_DIR }} --outpath ${{ secrets.DESTINATION_DIR }}/manifest.json" - name: Purge Cloudflare Cache - if: github.event_name == 'push' && github.ref_name == github.event.repository.default_branch + if: github.event_name == 'push' && github.ref_name == 'main' id: purge-cache uses: NathanVaughn/actions-cloudflare-purge@v3.1.0 with: diff --git a/README.md b/README.md index da10290d51d..866687d54b7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,12 @@ If you have the motivation and experience with Typescript/Javascript (or are wil 2. Run `npm run start:dev` to locally run the project in `localhost:8000` #### Linting -We're using ESLint as our common linter and formatter. It will run automatically during the pre-commit hook but if you would like to manually run it, use the `npm run eslint` script. +We're using ESLint as our common linter and formatter. It will run automatically during the pre-commit hook but if you would like to manually run it, use the `npm run eslint` script. To view the complete rules, check out the [eslint.config.js](./eslint.config.js) file. + +### 📚 Documentation +You can find the auto-generated documentation [here](https://pagefaultgames.github.io/pokerogue/main/index.html). +For information on enemy AI, check out the [enemy-ai.md](./docs/enemy-ai.md) file. +For detailed guidelines on documenting your code, refer to the [comments.md](./docs/comments.md) file. ### ❔ FAQ diff --git a/create-test-boilerplate.js b/create-test-boilerplate.js index 5f4bbc41198..a365999c623 100644 --- a/create-test-boilerplate.js +++ b/create-test-boilerplate.js @@ -49,7 +49,7 @@ async function promptFileName(selectedType) { { type: "input", name: "userInput", - message: `Please provide a file name for the ${selectedType} test:`, + message: `Please provide the name of the ${selectedType}:`, }, ]); @@ -110,7 +110,7 @@ import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("${description}", () => { let phaserGame: Phaser.Game; @@ -129,15 +129,22 @@ describe("${description}", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.SPLASH]) + .moveset([ Moves.SPLASH ]) + .ability(Abilities.BALL_FETCH) .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH); }); - it("test case", async () => { - // await game.classicMode.startBattle([Species.MAGIKARP]); - // game.move.select(Moves.SPLASH); + it("should do X", async () => { + await game.classicMode.startBattle([ Species.FEEBAS ]); + + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to("BerryPhase"); + + expect(true).toBe(true); }); }); `; diff --git a/eslint.config.js b/eslint.config.js index 80e9e67b525..2f2b466c66f 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,5 +1,5 @@ import tseslint from '@typescript-eslint/eslint-plugin'; -import stylisticTs from '@stylistic/eslint-plugin-ts' +import stylisticTs from '@stylistic/eslint-plugin-ts'; import parser from '@typescript-eslint/parser'; import importX from 'eslint-plugin-import-x'; @@ -16,15 +16,15 @@ export default [ '@typescript-eslint': tseslint }, rules: { - "eqeqeq": ["error", "always"], // Enforces the use of === and !== instead of == and != - "indent": ["error", 2], // Enforces a 2-space indentation + "eqeqeq": ["error", "always"], // Enforces the use of `===` and `!==` instead of `==` and `!=` + "indent": ["error", 2, { "SwitchCase": 1 }], // Enforces a 2-space indentation, enforces indentation of `case ...:` statements "quotes": ["error", "double"], // Enforces the use of double quotes for strings - "no-var": "error", // Disallows the use of var, enforcing let or const instead - "prefer-const": "error", // Prefers the use of const for variables that are never reassigned + "no-var": "error", // Disallows the use of `var`, enforcing `let` or `const` instead + "prefer-const": "error", // Enforces the use of `const` for variables that are never reassigned "no-undef": "off", // Disables the rule that disallows the use of undeclared variables (TypeScript handles this) "@typescript-eslint/no-unused-vars": [ "error", { "args": "none", // Allows unused function parameters. Useful for functions with specific signatures where not all parameters are always used. - "ignoreRestSiblings": true // Allows unused variables that are part of a rest property in object destructuring. Useful for excluding certain properties from an object while using the rest. + "ignoreRestSiblings": true // Allows unused variables that are part of a rest property in object destructuring. Useful for excluding certain properties from an object while using the others. }], "eol-last": ["error", "always"], // Enforces at least one newline at the end of files "@stylistic/ts/semi": ["error", "always"], // Requires semicolons for TypeScript-specific syntax @@ -32,15 +32,20 @@ export default [ "no-extra-semi": ["error"], // Disallows unnecessary semicolons for TypeScript-specific syntax "brace-style": "off", // Note: you must disable the base rule as it can report incorrect errors "curly": ["error", "all"], // Enforces the use of curly braces for all control statements - "@stylistic/ts/brace-style": ["error", "1tbs"], + "@stylistic/ts/brace-style": ["error", "1tbs"], // Enforces the following brace style: https://eslint.style/rules/js/brace-style#_1tbs "no-trailing-spaces": ["error", { // Disallows trailing whitespace at the end of lines "skipBlankLines": false, // Enforces the rule even on blank lines "ignoreComments": false // Enforces the rule on lines containing comments }], "space-before-blocks": ["error", "always"], // Enforces a space before blocks "keyword-spacing": ["error", { "before": true, "after": true }], // Enforces spacing before and after keywords - "comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after comma + "comma-spacing": ["error", { "before": false, "after": true }], // Enforces spacing after commas "import-x/extensions": ["error", "never", { "json": "always" }], // Enforces no extension for imports unless json + "array-bracket-spacing": ["error", "always", { "objectsInArrays": false, "arraysInArrays": false }], // Enforces consistent spacing inside array brackets + "object-curly-spacing": ["error", "always", { "arraysInObjects": false, "objectsInObjects": false }], // Enforces consistent spacing inside braces of object literals, destructuring assignments, and import/export specifiers + "computed-property-spacing": ["error", "never" ], // Enforces consistent spacing inside computed property brackets + "space-infix-ops": ["error", { "int32Hint": false }], // Enforces spacing around infix operators + "no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }], // Disallows multiple empty lines } } ] diff --git a/global.d.ts b/global.d.ts new file mode 100644 index 00000000000..f4dfa7d4cb2 --- /dev/null +++ b/global.d.ts @@ -0,0 +1,14 @@ +import type { SetupServerApi } from "msw/node"; + +export {}; + +declare global { + /** + * Only used in testing. + * Can technically be undefined/null but for ease of use we are going to assume it is always defined. + * Used to load i18n files exclusively. + * + * To set up your own server in a test see `game_data.test.ts` + */ + var i18nServer: SetupServerApi; +} diff --git a/package-lock.json b/package-lock.json index f633d427d6d..be946306471 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,13 @@ { "name": "pokemon-rogue-battle", - "version": "1.0.4", + "version": "1.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pokemon-rogue-battle", - "version": "1.0.4", + "version": "1.1.0", + "hasInstallScript": true, "dependencies": { "@material/material-color-utilities": "^0.2.7", "crypto-js": "^4.2.0", diff --git a/package.json b/package.json index d8d7f5e8db8..a31296d1644 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.0.4", + "version": "1.1.0", "type": "module", "scripts": { "start": "vite", @@ -20,7 +20,7 @@ "depcruise": "depcruise src", "depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg", "create-test": "node ./create-test-boilerplate.js", - "postinstall": "npx lefthook install && npx lefthook run post-merge" + "postinstall": "npx lefthook install && npx lefthook run post-merge" }, "devDependencies": { "@eslint/js": "^9.3.0", diff --git a/public/audio/cry/718-10-complete.m4a b/public/audio/cry/718-10-complete.m4a new file mode 100644 index 00000000000..94d95360553 Binary files /dev/null and b/public/audio/cry/718-10-complete.m4a differ diff --git a/public/images/pokemon/275.png b/public/images/pokemon/275.png index 07a6fe725ad..61f98ed1655 100644 Binary files a/public/images/pokemon/275.png and b/public/images/pokemon/275.png differ diff --git a/public/images/pokemon/281.json b/public/images/pokemon/281.json index 8e865cdc935..cb1a43f256f 100644 --- a/public/images/pokemon/281.json +++ b/public/images/pokemon/281.json @@ -399,13 +399,13 @@ "x": 0, "y": 6, "w": 36, - "h": 55 + "h": 54 }, "frame": { "x": 72, "y": 55, "w": 36, - "h": 55 + "h": 54 } }, { @@ -420,13 +420,13 @@ "x": 0, "y": 6, "w": 36, - "h": 55 + "h": 54 }, "frame": { "x": 72, "y": 55, "w": 36, - "h": 55 + "h": 54 } }, { diff --git a/public/images/pokemon/436.json b/public/images/pokemon/436.json index dc6c1d23770..6206c5e66cb 100644 --- a/public/images/pokemon/436.json +++ b/public/images/pokemon/436.json @@ -1,2666 +1,1019 @@ -{ - "textures": [ - { - "image": "436.png", - "format": "RGBA8888", - "size": { - "w": 97, - "h": 97 - }, - "scale": 1, - "frames": [ - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 13, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 13, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 4, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 4, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 13, - "y": 14, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 13, - "y": 14, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 17, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 17, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 18, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 18, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 15, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 15, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 32, - "h": 39 - }, - "frame": { - "x": 33, - "y": 0, - "w": 32, - "h": 39 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 32, - "h": 39 - }, - "frame": { - "x": 33, - "y": 0, - "w": 32, - "h": 39 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 15, - "y": 9, - "w": 32, - "h": 39 - }, - "frame": { - "x": 65, - "y": 0, - "w": 32, - "h": 39 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 15, - "y": 9, - "w": 32, - "h": 39 - }, - "frame": { - "x": 65, - "y": 0, - "w": 32, - "h": 39 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 33, - "h": 38 - }, - "frame": { - "x": 0, - "y": 39, - "w": 33, - "h": 38 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 33, - "h": 38 - }, - "frame": { - "x": 0, - "y": 39, - "w": 33, - "h": 38 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 21, - "w": 33, - "h": 38 - }, - "frame": { - "x": 33, - "y": 39, - "w": 33, - "h": 38 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 21, - "w": 33, - "h": 38 - }, - "frame": { - "x": 33, - "y": 39, - "w": 33, - "h": 38 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:2b46b60048375cd75fb24de5f2dd05a3:de64de523e63943f7f5dc5a59d03e108:0a3bacf3d680738b160c4c8ace3cda59$" - } -} +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0002.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0003.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0004.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0005.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0006.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0007.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0008.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0009.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0010.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0011.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0012.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0013.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0014.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0015.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0016.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0017.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0018.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0019.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0020.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0021.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0022.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0023.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0024.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0025.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0026.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0027.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0028.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0029.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0030.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0031.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0032.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0033.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0034.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0035.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0036.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0037.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0038.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0039.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0040.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0041.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0042.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0043.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0044.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0045.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0046.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0047.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0048.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0049.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0050.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0051.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0052.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0053.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0054.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0055.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0056.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0057.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0058.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0059.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 6, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0060.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 6, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0061.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0062.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0063.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0064.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0065.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0066.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0067.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0068.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0069.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0070.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0071.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0072.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0073.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0074.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0075.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0076.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0077.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 4, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0078.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 4, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0079.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 3, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0080.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 3, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0081.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 4, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0082.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 4, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0083.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0084.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0085.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0086.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0087.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0088.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0089.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0090.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0091.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0092.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0093.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0094.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0095.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 5, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0096.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 5, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0097.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 1, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0098.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 1, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0099.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 0, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0100.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 0, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0101.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 5, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0102.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 5, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0103.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 16, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0104.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 16, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0105.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 15, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0106.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 15, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0107.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 18, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0108.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 18, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0109.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 22, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0110.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 22, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0111.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 19, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0112.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 19, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0113.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0114.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0115.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0116.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0117.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0118.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0119.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0120.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0121.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0122.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0123.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0124.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0125.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0126.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.7-dev", + "image": "436.png", + "format": "RGBA8888", + "size": { "w": 31, "h": 37 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/436.png b/public/images/pokemon/436.png index 1ca185baecd..0308cb7303a 100644 Binary files a/public/images/pokemon/436.png and b/public/images/pokemon/436.png differ diff --git a/public/images/pokemon/451.json b/public/images/pokemon/451.json index 3a320a87c61..0e99c96f876 100644 --- a/public/images/pokemon/451.json +++ b/public/images/pokemon/451.json @@ -1,715 +1,2330 @@ -{ "frames": [ - { - "filename": "0001.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0002.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0003.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0004.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0005.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0006.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0007.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0008.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0009.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0010.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0011.png", - "frame": { "x": 68, "y": 0, "w": 64, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 4, "w": 64, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0012.png", - "frame": { "x": 68, "y": 0, "w": 64, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 4, "w": 64, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0013.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0014.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0015.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0016.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0017.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0018.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0019.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0020.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0021.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0022.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0023.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0024.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0025.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0026.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0027.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0028.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0029.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0030.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0031.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0032.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0033.png", - "frame": { "x": 68, "y": 0, "w": 64, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 4, "w": 64, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0034.png", - "frame": { "x": 68, "y": 0, "w": 64, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 4, "w": 64, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0035.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0036.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0037.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0038.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0039.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0040.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0041.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0042.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0043.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0044.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0045.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0046.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0047.png", - "frame": { "x": 232, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0048.png", - "frame": { "x": 232, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0049.png", - "frame": { "x": 117, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0050.png", - "frame": { "x": 117, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0051.png", - "frame": { "x": 117, "y": 42, "w": 60, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 60, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0052.png", - "frame": { "x": 117, "y": 42, "w": 60, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 60, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0053.png", - "frame": { "x": 132, "y": 0, "w": 63, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 63, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0054.png", - "frame": { "x": 132, "y": 0, "w": 63, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 63, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0055.png", - "frame": { "x": 0, "y": 0, "w": 68, "h": 40 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 6, "w": 68, "h": 40 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0056.png", - "frame": { "x": 0, "y": 0, "w": 68, "h": 40 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 6, "w": 68, "h": 40 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0057.png", - "frame": { "x": 195, "y": 0, "w": 63, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 63, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0058.png", - "frame": { "x": 195, "y": 0, "w": 63, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 63, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0059.png", - "frame": { "x": 258, "y": 0, "w": 61, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 3, "w": 61, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0060.png", - "frame": { "x": 258, "y": 0, "w": 61, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 3, "w": 61, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0061.png", - "frame": { "x": 58, "y": 42, "w": 59, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 2, "w": 59, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0062.png", - "frame": { "x": 58, "y": 42, "w": 59, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 2, "w": 59, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0063.png", - "frame": { "x": 0, "y": 40, "w": 58, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 1, "w": 58, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0064.png", - "frame": { "x": 0, "y": 40, "w": 58, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 1, "w": 58, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0065.png", - "frame": { "x": 177, "y": 84, "w": 55, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 0, "w": 55, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0066.png", - "frame": { "x": 177, "y": 84, "w": 55, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 0, "w": 55, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0067.png", - "frame": { "x": 0, "y": 129, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0068.png", - "frame": { "x": 0, "y": 129, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0069.png", - "frame": { "x": 112, "y": 129, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0070.png", - "frame": { "x": 112, "y": 129, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0071.png", - "frame": { "x": 167, "y": 130, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0072.png", - "frame": { "x": 167, "y": 130, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0073.png", - "frame": { "x": 0, "y": 173, "w": 54, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 54, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0074.png", - "frame": { "x": 0, "y": 173, "w": 54, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 54, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0075.png", - "frame": { "x": 54, "y": 177, "w": 52, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 52, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0076.png", - "frame": { "x": 54, "y": 177, "w": 52, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 52, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0077.png", - "frame": { "x": 210, "y": 176, "w": 53, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 0, "y": 2, "w": 53, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0078.png", - "frame": { "x": 210, "y": 176, "w": 53, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 0, "y": 2, "w": 53, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0079.png", - "frame": { "x": 158, "y": 174, "w": 52, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 1, "w": 52, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0080.png", - "frame": { "x": 158, "y": 174, "w": 52, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 1, "w": 52, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0081.png", - "frame": { "x": 222, "y": 131, "w": 53, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 1, "w": 53, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0082.png", - "frame": { "x": 222, "y": 131, "w": 53, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 1, "w": 53, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0083.png", - "frame": { "x": 275, "y": 132, "w": 53, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 1, "w": 53, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0084.png", - "frame": { "x": 275, "y": 132, "w": 53, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 1, "w": 53, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0085.png", - "frame": { "x": 55, "y": 131, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0086.png", - "frame": { "x": 55, "y": 131, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0087.png", - "frame": { "x": 107, "y": 173, "w": 51, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 51, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0088.png", - "frame": { "x": 107, "y": 173, "w": 51, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 51, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - } - ], - "meta": { - "app": "https://www.aseprite.org/", - "version": "1.3.8.1-x64", - "image": "451.png", - "format": "I8", - "size": { "w": 339, "h": 221 }, - "scale": "1" - } +{ + "textures": [ + { + "image": "451.png", + "format": "RGBA8888", + "size": { + "w": 281, + "h": 281 + }, + "scale": 1, + "frames": [ + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 69, + "h": 41 + }, + "frame": { + "x": 0, + "y": 0, + "w": 69, + "h": 41 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 69, + "h": 41 + }, + "frame": { + "x": 0, + "y": 0, + "w": 69, + "h": 41 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 69, + "h": 41 + }, + "frame": { + "x": 0, + "y": 0, + "w": 69, + "h": 41 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 69, + "h": 41 + }, + "frame": { + "x": 0, + "y": 0, + "w": 69, + "h": 41 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 66, + "h": 43 + }, + "frame": { + "x": 132, + "y": 0, + "w": 66, + "h": 43 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 66, + "h": 43 + }, + "frame": { + "x": 132, + "y": 0, + "w": 66, + "h": 43 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 66, + "h": 43 + }, + "frame": { + "x": 132, + "y": 0, + "w": 66, + "h": 43 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 66, + "h": 43 + }, + "frame": { + "x": 132, + "y": 0, + "w": 66, + "h": 43 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 198, + "y": 0, + "w": 65, + "h": 43 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 198, + "y": 0, + "w": 65, + "h": 43 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 198, + "y": 0, + "w": 65, + "h": 43 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 198, + "y": 0, + "w": 65, + "h": 43 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 0, + "y": 41, + "w": 65, + "h": 43 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 0, + "y": 41, + "w": 65, + "h": 43 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 0, + "y": 41, + "w": 65, + "h": 43 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 0, + "y": 41, + "w": 65, + "h": 43 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 62, + "h": 44 + }, + "frame": { + "x": 126, + "y": 43, + "w": 62, + "h": 44 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 62, + "h": 44 + }, + "frame": { + "x": 126, + "y": 43, + "w": 62, + "h": 44 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 62, + "h": 44 + }, + "frame": { + "x": 126, + "y": 43, + "w": 62, + "h": 44 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 62, + "h": 44 + }, + "frame": { + "x": 126, + "y": 43, + "w": 62, + "h": 44 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 63, + "h": 44 + }, + "frame": { + "x": 188, + "y": 43, + "w": 63, + "h": 44 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 63, + "h": 44 + }, + "frame": { + "x": 188, + "y": 43, + "w": 63, + "h": 44 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 63, + "h": 44 + }, + "frame": { + "x": 188, + "y": 43, + "w": 63, + "h": 44 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 63, + "h": 44 + }, + "frame": { + "x": 188, + "y": 43, + "w": 63, + "h": 44 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 59, + "y": 87, + "w": 59, + "h": 45 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 59, + "y": 87, + "w": 59, + "h": 45 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 59, + "y": 87, + "w": 59, + "h": 45 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 59, + "y": 87, + "w": 59, + "h": 45 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 61, + "h": 45 + }, + "frame": { + "x": 118, + "y": 87, + "w": 61, + "h": 45 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 61, + "h": 45 + }, + "frame": { + "x": 118, + "y": 87, + "w": 61, + "h": 45 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 61, + "h": 45 + }, + "frame": { + "x": 118, + "y": 87, + "w": 61, + "h": 45 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 61, + "h": 45 + }, + "frame": { + "x": 118, + "y": 87, + "w": 61, + "h": 45 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 179, + "y": 87, + "w": 57, + "h": 45 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 179, + "y": 87, + "w": 57, + "h": 45 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 0, + "y": 129, + "w": 57, + "h": 45 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 0, + "y": 129, + "w": 57, + "h": 45 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 57, + "y": 132, + "w": 57, + "h": 45 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 57, + "y": 132, + "w": 57, + "h": 45 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 56, + "h": 45 + }, + "frame": { + "x": 114, + "y": 132, + "w": 56, + "h": 45 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 56, + "h": 45 + }, + "frame": { + "x": 114, + "y": 132, + "w": 56, + "h": 45 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 54, + "h": 45 + }, + "frame": { + "x": 170, + "y": 132, + "w": 54, + "h": 45 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 54, + "h": 45 + }, + "frame": { + "x": 170, + "y": 132, + "w": 54, + "h": 45 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 1, + "w": 54, + "h": 45 + }, + "frame": { + "x": 224, + "y": 132, + "w": 54, + "h": 45 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 1, + "w": 54, + "h": 45 + }, + "frame": { + "x": 224, + "y": 132, + "w": 54, + "h": 45 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 111, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 111, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 111, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 111, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 60, + "h": 46 + }, + "frame": { + "x": 168, + "y": 177, + "w": 60, + "h": 46 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 60, + "h": 46 + }, + "frame": { + "x": 168, + "y": 177, + "w": 60, + "h": 46 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 60, + "h": 46 + }, + "frame": { + "x": 168, + "y": 177, + "w": 60, + "h": 46 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 60, + "h": 46 + }, + "frame": { + "x": 168, + "y": 177, + "w": 60, + "h": 46 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 53, + "h": 46 + }, + "frame": { + "x": 228, + "y": 177, + "w": 53, + "h": 46 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 53, + "h": 46 + }, + "frame": { + "x": 228, + "y": 177, + "w": 53, + "h": 46 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 220, + "w": 54, + "h": 46 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 220, + "w": 54, + "h": 46 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 223, + "w": 57, + "h": 46 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 223, + "w": 57, + "h": 46 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 223, + "w": 57, + "h": 46 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 223, + "w": 57, + "h": 46 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 55, + "h": 46 + }, + "frame": { + "x": 111, + "y": 223, + "w": 55, + "h": 46 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 55, + "h": 46 + }, + "frame": { + "x": 111, + "y": 223, + "w": 55, + "h": 46 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 55, + "h": 46 + }, + "frame": { + "x": 166, + "y": 223, + "w": 55, + "h": 46 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 55, + "h": 46 + }, + "frame": { + "x": 166, + "y": 223, + "w": 55, + "h": 46 + } + }, + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 221, + "y": 223, + "w": 54, + "h": 46 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 221, + "y": 223, + "w": 54, + "h": 46 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:e303c68c1876b77078f3e1fd4372a4ce:84139d6b94cea0f3c45dbd8fa7109c3d:c79e17c206de27e3b7f1ce96f7df8e51$" + } } diff --git a/public/images/pokemon/451.png b/public/images/pokemon/451.png index 716e8a08041..fac8f5a0170 100644 Binary files a/public/images/pokemon/451.png and b/public/images/pokemon/451.png differ diff --git a/public/images/pokemon/6706.png b/public/images/pokemon/6706.png index 44f627acd10..e967b550871 100644 Binary files a/public/images/pokemon/6706.png and b/public/images/pokemon/6706.png differ diff --git a/public/images/pokemon/back/436.json b/public/images/pokemon/back/436.json index 78014a69936..3342cc6577c 100644 --- a/public/images/pokemon/back/436.json +++ b/public/images/pokemon/back/436.json @@ -1,2666 +1,1019 @@ -{ - "textures": [ - { - "image": "436.png", - "format": "RGBA8888", - "size": { - "w": 100, - "h": 100 - }, - "scale": 1, - "frames": [ - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 13, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 13, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 1, - "y": 14, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 1, - "y": 14, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 17, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 17, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 18, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 18, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 15, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 15, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 15, - "y": 4, - "w": 33, - "h": 40 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 40 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 15, - "y": 4, - "w": 33, - "h": 40 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 40 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 0, - "y": 9, - "w": 33, - "h": 40 - }, - "frame": { - "x": 67, - "y": 0, - "w": 33, - "h": 40 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 0, - "y": 9, - "w": 33, - "h": 40 - }, - "frame": { - "x": 67, - "y": 0, - "w": 33, - "h": 40 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 34, - "h": 39 - }, - "frame": { - "x": 0, - "y": 40, - "w": 34, - "h": 39 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 34, - "h": 39 - }, - "frame": { - "x": 0, - "y": 40, - "w": 34, - "h": 39 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 21, - "w": 34, - "h": 39 - }, - "frame": { - "x": 34, - "y": 40, - "w": 34, - "h": 39 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 21, - "w": 34, - "h": 39 - }, - "frame": { - "x": 34, - "y": 40, - "w": 34, - "h": 39 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:6e466fdd2b62b8024ea52be04133391d:67fd60bf8d57184b168ae25f93bafcc2:0a3bacf3d680738b160c4c8ace3cda59$" - } -} +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0002.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0003.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0004.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0005.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0006.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0007.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0008.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0009.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0010.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0011.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0012.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0013.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0014.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0015.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0016.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0017.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0018.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0019.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0020.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0021.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0022.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0023.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0024.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0025.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0026.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0027.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0028.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0029.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0030.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0031.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0032.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0033.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0034.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0035.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0036.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0037.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0038.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0039.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0040.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0041.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0042.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0043.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0044.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0045.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0046.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0047.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0048.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0049.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0050.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0051.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0052.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0053.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0054.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0055.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0056.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0057.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0058.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0059.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 6, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0060.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 6, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0061.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0062.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0063.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0064.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0065.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0066.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0067.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0068.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0069.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0070.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0071.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0072.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0073.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0074.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0075.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0076.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0077.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 4, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0078.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 4, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0079.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 3, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0080.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 3, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0081.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 4, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0082.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 4, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0083.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0084.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0085.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0086.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0087.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0088.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0089.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0090.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0091.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0092.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0093.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0094.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0095.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 16, "y": 5, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0096.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 16, "y": 5, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0097.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 1, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0098.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 1, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0099.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 0, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0100.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 0, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0101.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 5, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0102.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 5, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0103.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0104.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0105.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 15, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0106.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 15, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0107.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 18, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0108.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 18, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0109.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 22, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0110.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 22, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0111.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 19, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0112.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 19, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0113.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0114.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0115.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0116.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0117.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0118.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0119.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0120.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0121.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0122.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0123.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0124.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0125.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0126.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.7-dev", + "image": "436.png", + "format": "I8", + "size": { "w": 32, "h": 38 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/back/436.png b/public/images/pokemon/back/436.png index de9a217f0cf..5d08304bff1 100644 Binary files a/public/images/pokemon/back/436.png and b/public/images/pokemon/back/436.png differ diff --git a/public/images/pokemon/back/6706.png b/public/images/pokemon/back/6706.png index e7620078a5b..82c64e98535 100644 Binary files a/public/images/pokemon/back/6706.png and b/public/images/pokemon/back/6706.png differ diff --git a/public/images/pokemon/back/shiny/436.json b/public/images/pokemon/back/shiny/436.json index 4091e1a2e49..3342cc6577c 100644 --- a/public/images/pokemon/back/shiny/436.json +++ b/public/images/pokemon/back/shiny/436.json @@ -1,2666 +1,1019 @@ -{ - "textures": [ - { - "image": "436.png", - "format": "RGBA8888", - "size": { - "w": 100, - "h": 100 - }, - "scale": 1, - "frames": [ - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 5, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 13, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 13, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 11, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 13, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 11, - "y": 0, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 1, - "y": 14, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 1, - "y": 14, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 17, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 4, - "y": 17, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 18, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 8, - "y": 18, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 15, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 15, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 6, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 10, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 34, - "h": 40 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 40 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 15, - "y": 4, - "w": 33, - "h": 40 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 40 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 15, - "y": 4, - "w": 33, - "h": 40 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 40 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 0, - "y": 9, - "w": 33, - "h": 40 - }, - "frame": { - "x": 67, - "y": 0, - "w": 33, - "h": 40 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 0, - "y": 9, - "w": 33, - "h": 40 - }, - "frame": { - "x": 67, - "y": 0, - "w": 33, - "h": 40 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 34, - "h": 39 - }, - "frame": { - "x": 0, - "y": 40, - "w": 34, - "h": 39 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 34, - "h": 39 - }, - "frame": { - "x": 0, - "y": 40, - "w": 34, - "h": 39 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 21, - "w": 34, - "h": 39 - }, - "frame": { - "x": 34, - "y": 40, - "w": 34, - "h": 39 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 48, - "h": 60 - }, - "spriteSourceSize": { - "x": 9, - "y": 21, - "w": 34, - "h": 39 - }, - "frame": { - "x": 34, - "y": 40, - "w": 34, - "h": 39 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:810e866f20256a6beca964ab2fe2f997:4d42b12e9664d852f2391c8b56845681:0a3bacf3d680738b160c4c8ace3cda59$" - } -} +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0002.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0003.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0004.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0005.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0006.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0007.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0008.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0009.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0010.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0011.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0012.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0013.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0014.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0015.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0016.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0017.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0018.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0019.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0020.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0021.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0022.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0023.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0024.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0025.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0026.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0027.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0028.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0029.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0030.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0031.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0032.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0033.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0034.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0035.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0036.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0037.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0038.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0039.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0040.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0041.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0042.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0043.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0044.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0045.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0046.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0047.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0048.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0049.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0050.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0051.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0052.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0053.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0054.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0055.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0056.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0057.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0058.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0059.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 6, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0060.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 6, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0061.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0062.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0063.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0064.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0065.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0066.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0067.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0068.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0069.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0070.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0071.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0072.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0073.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0074.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0075.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0076.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0077.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 4, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0078.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 4, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0079.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 3, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0080.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 3, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0081.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 4, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0082.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 4, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0083.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0084.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0085.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0086.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0087.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0088.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 12, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0089.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0090.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0091.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0092.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0093.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0094.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0095.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 16, "y": 5, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0096.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 16, "y": 5, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0097.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 1, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0098.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 1, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0099.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 0, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0100.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 0, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0101.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 5, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0102.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 5, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0103.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0104.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0105.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 15, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0106.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 15, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0107.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 18, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0108.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 18, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0109.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 22, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0110.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 22, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0111.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 19, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0112.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 19, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0113.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0114.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0115.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0116.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0117.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0118.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 10, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0119.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0120.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 7, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0121.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0122.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 9, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0123.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0124.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 11, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0125.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + }, + { + "filename": "0126.png", + "frame": { "x": 0, "y": 0, "w": 32, "h": 38 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 32, "h": 38 }, + "sourceSize": { "w": 48, "h": 60 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.7-dev", + "image": "436.png", + "format": "I8", + "size": { "w": 32, "h": 38 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/back/shiny/436.png b/public/images/pokemon/back/shiny/436.png index b3d6dc4df61..d766a912555 100644 Binary files a/public/images/pokemon/back/shiny/436.png and b/public/images/pokemon/back/shiny/436.png differ diff --git a/public/images/pokemon/exp/6706.png b/public/images/pokemon/exp/6706.png index ea745dfb04b..77b10183ec7 100644 Binary files a/public/images/pokemon/exp/6706.png and b/public/images/pokemon/exp/6706.png differ diff --git a/public/images/pokemon/exp/705.png b/public/images/pokemon/exp/705.png index 3413bcd9fa3..670e8be5d51 100644 Binary files a/public/images/pokemon/exp/705.png and b/public/images/pokemon/exp/705.png differ diff --git a/public/images/pokemon/exp/back/6706.png b/public/images/pokemon/exp/back/6706.png index 4bda5b08d10..7842bbbffad 100644 Binary files a/public/images/pokemon/exp/back/6706.png and b/public/images/pokemon/exp/back/6706.png differ diff --git a/public/images/pokemon/female/275.png b/public/images/pokemon/female/275.png index 7f251793a15..c3c358716b2 100644 Binary files a/public/images/pokemon/female/275.png and b/public/images/pokemon/female/275.png differ diff --git a/public/images/pokemon/shiny/275.png b/public/images/pokemon/shiny/275.png index fee57d64804..de8271cdbd2 100644 Binary files a/public/images/pokemon/shiny/275.png and b/public/images/pokemon/shiny/275.png differ diff --git a/public/images/pokemon/shiny/281.json b/public/images/pokemon/shiny/281.json index 684be77edf9..64e10c7f9a6 100644 --- a/public/images/pokemon/shiny/281.json +++ b/public/images/pokemon/shiny/281.json @@ -399,13 +399,13 @@ "x": 0, "y": 6, "w": 36, - "h": 55 + "h": 54 }, "frame": { "x": 72, "y": 55, "w": 36, - "h": 55 + "h": 54 } }, { @@ -420,13 +420,13 @@ "x": 0, "y": 6, "w": 36, - "h": 55 + "h": 54 }, "frame": { "x": 72, "y": 55, "w": 36, - "h": 55 + "h": 54 } }, { diff --git a/public/images/pokemon/shiny/436.json b/public/images/pokemon/shiny/436.json index 945a840b477..6206c5e66cb 100644 --- a/public/images/pokemon/shiny/436.json +++ b/public/images/pokemon/shiny/436.json @@ -1,2666 +1,1019 @@ -{ - "textures": [ - { - "image": "436.png", - "format": "RGBA8888", - "size": { - "w": 97, - "h": 97 - }, - "scale": 1, - "frames": [ - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 1, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 4, - "y": 3, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 2, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 3, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 13, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 13, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 11, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 1, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 4, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 11, - "y": 4, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 13, - "y": 14, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 13, - "y": 14, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 17, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 10, - "y": 17, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 18, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 6, - "y": 18, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 15, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 15, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 8, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 8, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 10, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 12, - "w": 33, - "h": 39 - }, - "frame": { - "x": 0, - "y": 0, - "w": 33, - "h": 39 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 32, - "h": 39 - }, - "frame": { - "x": 33, - "y": 0, - "w": 32, - "h": 39 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 32, - "h": 39 - }, - "frame": { - "x": 33, - "y": 0, - "w": 32, - "h": 39 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 15, - "y": 9, - "w": 32, - "h": 39 - }, - "frame": { - "x": 65, - "y": 0, - "w": 32, - "h": 39 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 15, - "y": 9, - "w": 32, - "h": 39 - }, - "frame": { - "x": 65, - "y": 0, - "w": 32, - "h": 39 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 33, - "h": 38 - }, - "frame": { - "x": 0, - "y": 39, - "w": 33, - "h": 38 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 7, - "y": 0, - "w": 33, - "h": 38 - }, - "frame": { - "x": 0, - "y": 39, - "w": 33, - "h": 38 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 21, - "w": 33, - "h": 38 - }, - "frame": { - "x": 33, - "y": 39, - "w": 33, - "h": 38 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 47, - "h": 59 - }, - "spriteSourceSize": { - "x": 5, - "y": 21, - "w": 33, - "h": 38 - }, - "frame": { - "x": 33, - "y": 39, - "w": 33, - "h": 38 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:de8b910298717773b7a2a224a56b3553:df42ff52dc55f342b76506445413ffee:0a3bacf3d680738b160c4c8ace3cda59$" - } -} +{ "frames": [ + { + "filename": "0001.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0002.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0003.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0004.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0005.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0006.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0007.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0008.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0009.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0010.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0011.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0012.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0013.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0014.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0015.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0016.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0017.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0018.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0019.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0020.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0021.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0022.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0023.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0024.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0025.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0026.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0027.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0028.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0029.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0030.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0031.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0032.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0033.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0034.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0035.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0036.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0037.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0038.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0039.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0040.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0041.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0042.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0043.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0044.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0045.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0046.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0047.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0048.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0049.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0050.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0051.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0052.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0053.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0054.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0055.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0056.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0057.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0058.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0059.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 6, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0060.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 6, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0061.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0062.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0063.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0064.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0065.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0066.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0067.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0068.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 10, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0069.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0070.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0071.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0072.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0073.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0074.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0075.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0076.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0077.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 4, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0078.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 5, "y": 4, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0079.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 3, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0080.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 3, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0081.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 4, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0082.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 4, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0083.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0084.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0085.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0086.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0087.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0088.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 12, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0089.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0090.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0091.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0092.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0093.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0094.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 2, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0095.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 5, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0096.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 0, "y": 5, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0097.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 1, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0098.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 4, "y": 1, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0099.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 0, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0100.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 0, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0101.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 5, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0102.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 12, "y": 5, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0103.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 16, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0104.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 16, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0105.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 15, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0106.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 14, "y": 15, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0107.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 18, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0108.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 11, "y": 18, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0109.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 22, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0110.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 6, "y": 22, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0111.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 19, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0112.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 7, "y": 19, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0113.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0114.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 16, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0115.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0116.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 9, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0117.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0118.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 10, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0119.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0120.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 7, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0121.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0122.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 9, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0123.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0124.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 11, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0125.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + }, + { + "filename": "0126.png", + "frame": { "x": 0, "y": 0, "w": 31, "h": 37 }, + "rotated": false, + "trimmed": true, + "spriteSourceSize": { "x": 8, "y": 13, "w": 31, "h": 37 }, + "sourceSize": { "w": 47, "h": 59 } + } + ], + "meta": { + "app": "https://www.aseprite.org/", + "version": "1.3.7-dev", + "image": "436.png", + "format": "RGBA8888", + "size": { "w": 31, "h": 37 }, + "scale": "1" + } +} diff --git a/public/images/pokemon/shiny/436.png b/public/images/pokemon/shiny/436.png index 59003ba85dc..87263bbbe6c 100644 Binary files a/public/images/pokemon/shiny/436.png and b/public/images/pokemon/shiny/436.png differ diff --git a/public/images/pokemon/shiny/451.json b/public/images/pokemon/shiny/451.json index 3a320a87c61..f492cdbcb04 100644 --- a/public/images/pokemon/shiny/451.json +++ b/public/images/pokemon/shiny/451.json @@ -1,715 +1,2330 @@ -{ "frames": [ - { - "filename": "0001.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0002.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0003.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0004.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0005.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0006.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0007.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0008.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0009.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0010.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0011.png", - "frame": { "x": 68, "y": 0, "w": 64, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 4, "w": 64, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0012.png", - "frame": { "x": 68, "y": 0, "w": 64, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 4, "w": 64, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0013.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0014.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0015.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0016.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0017.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0018.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0019.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0020.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0021.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0022.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0023.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0024.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0025.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0026.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0027.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0028.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0029.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0030.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0031.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0032.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0033.png", - "frame": { "x": 68, "y": 0, "w": 64, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 4, "w": 64, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0034.png", - "frame": { "x": 68, "y": 0, "w": 64, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 4, "w": 64, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0035.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0036.png", - "frame": { "x": 177, "y": 42, "w": 61, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 61, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0037.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0038.png", - "frame": { "x": 238, "y": 43, "w": 59, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 59, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0039.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0040.png", - "frame": { "x": 0, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0041.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0042.png", - "frame": { "x": 57, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0043.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0044.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0045.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0046.png", - "frame": { "x": 287, "y": 86, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0047.png", - "frame": { "x": 232, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0048.png", - "frame": { "x": 232, "y": 86, "w": 55, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 1, "w": 55, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0049.png", - "frame": { "x": 117, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0050.png", - "frame": { "x": 117, "y": 85, "w": 57, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 2, "w": 57, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0051.png", - "frame": { "x": 117, "y": 42, "w": 60, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 60, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0052.png", - "frame": { "x": 117, "y": 42, "w": 60, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 5, "y": 3, "w": 60, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0053.png", - "frame": { "x": 132, "y": 0, "w": 63, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 63, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0054.png", - "frame": { "x": 132, "y": 0, "w": 63, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 63, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0055.png", - "frame": { "x": 0, "y": 0, "w": 68, "h": 40 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 6, "w": 68, "h": 40 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0056.png", - "frame": { "x": 0, "y": 0, "w": 68, "h": 40 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 6, "w": 68, "h": 40 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0057.png", - "frame": { "x": 195, "y": 0, "w": 63, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 63, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0058.png", - "frame": { "x": 195, "y": 0, "w": 63, "h": 42 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 4, "w": 63, "h": 42 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0059.png", - "frame": { "x": 258, "y": 0, "w": 61, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 3, "w": 61, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0060.png", - "frame": { "x": 258, "y": 0, "w": 61, "h": 43 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 3, "w": 61, "h": 43 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0061.png", - "frame": { "x": 58, "y": 42, "w": 59, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 2, "w": 59, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0062.png", - "frame": { "x": 58, "y": 42, "w": 59, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 2, "w": 59, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0063.png", - "frame": { "x": 0, "y": 40, "w": 58, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 1, "w": 58, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0064.png", - "frame": { "x": 0, "y": 40, "w": 58, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 1, "w": 58, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0065.png", - "frame": { "x": 177, "y": 84, "w": 55, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 0, "w": 55, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0066.png", - "frame": { "x": 177, "y": 84, "w": 55, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 0, "w": 55, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0067.png", - "frame": { "x": 0, "y": 129, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0068.png", - "frame": { "x": 0, "y": 129, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0069.png", - "frame": { "x": 112, "y": 129, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0070.png", - "frame": { "x": 112, "y": 129, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0071.png", - "frame": { "x": 167, "y": 130, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0072.png", - "frame": { "x": 167, "y": 130, "w": 55, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 55, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0073.png", - "frame": { "x": 0, "y": 173, "w": 54, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 54, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0074.png", - "frame": { "x": 0, "y": 173, "w": 54, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 54, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0075.png", - "frame": { "x": 54, "y": 177, "w": 52, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 52, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0076.png", - "frame": { "x": 54, "y": 177, "w": 52, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 2, "w": 52, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0077.png", - "frame": { "x": 210, "y": 176, "w": 53, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 0, "y": 2, "w": 53, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0078.png", - "frame": { "x": 210, "y": 176, "w": 53, "h": 44 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 0, "y": 2, "w": 53, "h": 44 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0079.png", - "frame": { "x": 158, "y": 174, "w": 52, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 1, "w": 52, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0080.png", - "frame": { "x": 158, "y": 174, "w": 52, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 2, "y": 1, "w": 52, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0081.png", - "frame": { "x": 222, "y": 131, "w": 53, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 1, "w": 53, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0082.png", - "frame": { "x": 222, "y": 131, "w": 53, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 3, "y": 1, "w": 53, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0083.png", - "frame": { "x": 275, "y": 132, "w": 53, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 1, "w": 53, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0084.png", - "frame": { "x": 275, "y": 132, "w": 53, "h": 45 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 4, "y": 1, "w": 53, "h": 45 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0085.png", - "frame": { "x": 55, "y": 131, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0086.png", - "frame": { "x": 55, "y": 131, "w": 52, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 6, "y": 0, "w": 52, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0087.png", - "frame": { "x": 107, "y": 173, "w": 51, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 51, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - }, - { - "filename": "0088.png", - "frame": { "x": 107, "y": 173, "w": 51, "h": 46 }, - "rotated": false, - "trimmed": true, - "spriteSourceSize": { "x": 7, "y": 0, "w": 51, "h": 46 }, - "sourceSize": { "w": 71, "h": 46 } - } - ], - "meta": { - "app": "https://www.aseprite.org/", - "version": "1.3.8.1-x64", - "image": "451.png", - "format": "I8", - "size": { "w": 339, "h": 221 }, - "scale": "1" - } +{ + "textures": [ + { + "image": "451.png", + "format": "RGBA8888", + "size": { + "w": 281, + "h": 281 + }, + "scale": 1, + "frames": [ + { + "filename": "0033.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 69, + "h": 41 + }, + "frame": { + "x": 0, + "y": 0, + "w": 69, + "h": 41 + } + }, + { + "filename": "0034.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 69, + "h": 41 + }, + "frame": { + "x": 0, + "y": 0, + "w": 69, + "h": 41 + } + }, + { + "filename": "0077.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 69, + "h": 41 + }, + "frame": { + "x": 0, + "y": 0, + "w": 69, + "h": 41 + } + }, + { + "filename": "0078.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 5, + "w": 69, + "h": 41 + }, + "frame": { + "x": 0, + "y": 0, + "w": 69, + "h": 41 + } + }, + { + "filename": "0009.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0010.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0013.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0014.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0053.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0054.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0057.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0058.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 63, + "h": 43 + }, + "frame": { + "x": 69, + "y": 0, + "w": 63, + "h": 43 + } + }, + { + "filename": "0011.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 66, + "h": 43 + }, + "frame": { + "x": 132, + "y": 0, + "w": 66, + "h": 43 + } + }, + { + "filename": "0012.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 66, + "h": 43 + }, + "frame": { + "x": 132, + "y": 0, + "w": 66, + "h": 43 + } + }, + { + "filename": "0055.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 66, + "h": 43 + }, + "frame": { + "x": 132, + "y": 0, + "w": 66, + "h": 43 + } + }, + { + "filename": "0056.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 3, + "w": 66, + "h": 43 + }, + "frame": { + "x": 132, + "y": 0, + "w": 66, + "h": 43 + } + }, + { + "filename": "0031.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 198, + "y": 0, + "w": 65, + "h": 43 + } + }, + { + "filename": "0032.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 198, + "y": 0, + "w": 65, + "h": 43 + } + }, + { + "filename": "0075.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 198, + "y": 0, + "w": 65, + "h": 43 + } + }, + { + "filename": "0076.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 198, + "y": 0, + "w": 65, + "h": 43 + } + }, + { + "filename": "0035.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 0, + "y": 41, + "w": 65, + "h": 43 + } + }, + { + "filename": "0036.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 0, + "y": 41, + "w": 65, + "h": 43 + } + }, + { + "filename": "0079.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 0, + "y": 41, + "w": 65, + "h": 43 + } + }, + { + "filename": "0080.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 3, + "w": 65, + "h": 43 + }, + "frame": { + "x": 0, + "y": 41, + "w": 65, + "h": 43 + } + }, + { + "filename": "0007.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0008.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0015.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0016.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0051.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0052.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0059.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0060.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 61, + "h": 44 + }, + "frame": { + "x": 65, + "y": 43, + "w": 61, + "h": 44 + } + }, + { + "filename": "0029.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 62, + "h": 44 + }, + "frame": { + "x": 126, + "y": 43, + "w": 62, + "h": 44 + } + }, + { + "filename": "0030.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 62, + "h": 44 + }, + "frame": { + "x": 126, + "y": 43, + "w": 62, + "h": 44 + } + }, + { + "filename": "0073.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 62, + "h": 44 + }, + "frame": { + "x": 126, + "y": 43, + "w": 62, + "h": 44 + } + }, + { + "filename": "0074.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 4, + "y": 2, + "w": 62, + "h": 44 + }, + "frame": { + "x": 126, + "y": 43, + "w": 62, + "h": 44 + } + }, + { + "filename": "0037.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 63, + "h": 44 + }, + "frame": { + "x": 188, + "y": 43, + "w": 63, + "h": 44 + } + }, + { + "filename": "0038.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 63, + "h": 44 + }, + "frame": { + "x": 188, + "y": 43, + "w": 63, + "h": 44 + } + }, + { + "filename": "0081.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 63, + "h": 44 + }, + "frame": { + "x": 188, + "y": 43, + "w": 63, + "h": 44 + } + }, + { + "filename": "0082.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 2, + "w": 63, + "h": 44 + }, + "frame": { + "x": 188, + "y": 43, + "w": 63, + "h": 44 + } + }, + { + "filename": "0005.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0006.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0017.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0018.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0049.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0050.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0061.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0062.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 0, + "y": 84, + "w": 59, + "h": 45 + } + }, + { + "filename": "0027.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 59, + "y": 87, + "w": 59, + "h": 45 + } + }, + { + "filename": "0028.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 59, + "y": 87, + "w": 59, + "h": 45 + } + }, + { + "filename": "0071.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 59, + "y": 87, + "w": 59, + "h": 45 + } + }, + { + "filename": "0072.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 1, + "w": 59, + "h": 45 + }, + "frame": { + "x": 59, + "y": 87, + "w": 59, + "h": 45 + } + }, + { + "filename": "0039.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 61, + "h": 45 + }, + "frame": { + "x": 118, + "y": 87, + "w": 61, + "h": 45 + } + }, + { + "filename": "0040.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 61, + "h": 45 + }, + "frame": { + "x": 118, + "y": 87, + "w": 61, + "h": 45 + } + }, + { + "filename": "0083.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 61, + "h": 45 + }, + "frame": { + "x": 118, + "y": 87, + "w": 61, + "h": 45 + } + }, + { + "filename": "0084.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 1, + "w": 61, + "h": 45 + }, + "frame": { + "x": 118, + "y": 87, + "w": 61, + "h": 45 + } + }, + { + "filename": "0089.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 179, + "y": 87, + "w": 57, + "h": 45 + } + }, + { + "filename": "0090.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 179, + "y": 87, + "w": 57, + "h": 45 + } + }, + { + "filename": "0091.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 0, + "y": 129, + "w": 57, + "h": 45 + } + }, + { + "filename": "0092.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 0, + "y": 129, + "w": 57, + "h": 45 + } + }, + { + "filename": "0093.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 57, + "y": 132, + "w": 57, + "h": 45 + } + }, + { + "filename": "0094.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 57, + "h": 45 + }, + "frame": { + "x": 57, + "y": 132, + "w": 57, + "h": 45 + } + }, + { + "filename": "0095.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 56, + "h": 45 + }, + "frame": { + "x": 114, + "y": 132, + "w": 56, + "h": 45 + } + }, + { + "filename": "0096.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 56, + "h": 45 + }, + "frame": { + "x": 114, + "y": 132, + "w": 56, + "h": 45 + } + }, + { + "filename": "0097.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 54, + "h": 45 + }, + "frame": { + "x": 170, + "y": 132, + "w": 54, + "h": 45 + } + }, + { + "filename": "0098.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 1, + "w": 54, + "h": 45 + }, + "frame": { + "x": 170, + "y": 132, + "w": 54, + "h": 45 + } + }, + { + "filename": "0099.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 1, + "w": 54, + "h": 45 + }, + "frame": { + "x": 224, + "y": 132, + "w": 54, + "h": 45 + } + }, + { + "filename": "0100.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 0, + "y": 1, + "w": 54, + "h": 45 + }, + "frame": { + "x": 224, + "y": 132, + "w": 54, + "h": 45 + } + }, + { + "filename": "0001.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0002.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0021.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0022.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0023.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0024.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0045.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0046.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0065.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0066.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0067.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0068.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 174, + "w": 54, + "h": 46 + } + }, + { + "filename": "0003.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0004.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0019.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0020.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0047.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0048.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0063.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0064.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0025.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 111, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0026.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 111, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0069.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 111, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0070.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 111, + "y": 177, + "w": 57, + "h": 46 + } + }, + { + "filename": "0041.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 60, + "h": 46 + }, + "frame": { + "x": 168, + "y": 177, + "w": 60, + "h": 46 + } + }, + { + "filename": "0042.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 60, + "h": 46 + }, + "frame": { + "x": 168, + "y": 177, + "w": 60, + "h": 46 + } + }, + { + "filename": "0085.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 60, + "h": 46 + }, + "frame": { + "x": 168, + "y": 177, + "w": 60, + "h": 46 + } + }, + { + "filename": "0086.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 60, + "h": 46 + }, + "frame": { + "x": 168, + "y": 177, + "w": 60, + "h": 46 + } + }, + { + "filename": "0109.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 53, + "h": 46 + }, + "frame": { + "x": 228, + "y": 177, + "w": 53, + "h": 46 + } + }, + { + "filename": "0110.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 6, + "y": 0, + "w": 53, + "h": 46 + }, + "frame": { + "x": 228, + "y": 177, + "w": 53, + "h": 46 + } + }, + { + "filename": "0101.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 220, + "w": 54, + "h": 46 + } + }, + { + "filename": "0102.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 1, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 0, + "y": 220, + "w": 54, + "h": 46 + } + }, + { + "filename": "0043.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 223, + "w": 57, + "h": 46 + } + }, + { + "filename": "0044.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 223, + "w": 57, + "h": 46 + } + }, + { + "filename": "0087.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 223, + "w": 57, + "h": 46 + } + }, + { + "filename": "0088.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 57, + "h": 46 + }, + "frame": { + "x": 54, + "y": 223, + "w": 57, + "h": 46 + } + }, + { + "filename": "0103.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 55, + "h": 46 + }, + "frame": { + "x": 111, + "y": 223, + "w": 55, + "h": 46 + } + }, + { + "filename": "0104.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 2, + "y": 0, + "w": 55, + "h": 46 + }, + "frame": { + "x": 111, + "y": 223, + "w": 55, + "h": 46 + } + }, + { + "filename": "0105.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 55, + "h": 46 + }, + "frame": { + "x": 166, + "y": 223, + "w": 55, + "h": 46 + } + }, + { + "filename": "0106.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 3, + "y": 0, + "w": 55, + "h": 46 + }, + "frame": { + "x": 166, + "y": 223, + "w": 55, + "h": 46 + } + }, + { + "filename": "0107.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 221, + "y": 223, + "w": 54, + "h": 46 + } + }, + { + "filename": "0108.png", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 71, + "h": 46 + }, + "spriteSourceSize": { + "x": 5, + "y": 0, + "w": 54, + "h": 46 + }, + "frame": { + "x": 221, + "y": 223, + "w": 54, + "h": 46 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:9097bf5ffed4b93401c65aa14299faaa:d22b7c7f6e33b1453fda428e689d4529:c79e17c206de27e3b7f1ce96f7df8e51$" + } } diff --git a/public/images/pokemon/shiny/451.png b/public/images/pokemon/shiny/451.png index 4f8120ce668..69d165c9ae8 100644 Binary files a/public/images/pokemon/shiny/451.png and b/public/images/pokemon/shiny/451.png differ diff --git a/public/images/pokemon/shiny/female/275.png b/public/images/pokemon/shiny/female/275.png index c8f9a90b721..a0571493279 100644 Binary files a/public/images/pokemon/shiny/female/275.png and b/public/images/pokemon/shiny/female/275.png differ diff --git a/public/images/pokemon/variant/6706.json b/public/images/pokemon/variant/6706.json new file mode 100644 index 00000000000..2b9ead28219 --- /dev/null +++ b/public/images/pokemon/variant/6706.json @@ -0,0 +1,40 @@ +{ + "1": { + "566678": "0e6296", + "e0e4f4": "513981", + "625287": "4e4094", + "536273": "1f1233", + "988b98": "b24c86", + "9170b9": "8b69c3", + "c4cce1": "3b235c", + "e6d3e9": "f1a4c5", + "bfacc1": "da75a5", + "515f70": "197497", + "c5cee3": "63cee1", + "8e96aa": "301848", + "8b93a6": "3aa8c4", + "80737f": "8a2166", + "4b454f": "6f1357", + "36404c": "0c5474", + "b791f2": "c7a1e5" + }, + "2": { + "566678": "8e480b", + "e0e4f4": "176463", + "625287": "274159", + "536273": "02262c", + "988b98": "2a6563", + "9170b9": "2f667c", + "c4cce1": "0d484a", + "e6d3e9": "9cead8", + "bfacc1": "5db6a9", + "515f70": "a34205", + "c5cee3": "f7af58", + "8e96aa": "073338", + "8b93a6": "d27e26", + "80737f": "2b736f", + "4b454f": "194f51", + "36404c": "842401", + "b791f2": "4a9699" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/6706_2.json b/public/images/pokemon/variant/6706_2.json deleted file mode 100644 index f6bbf20116e..00000000000 --- a/public/images/pokemon/variant/6706_2.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "textures": [ - { - "image": "6706_2.png", - "format": "RGBA8888", - "size": { - "w": 82, - "h": 82 - }, - "scale": 1, - "frames": [ - { - "filename": "0001.png", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 82, - "h": 72 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 82, - "h": 72 - }, - "frame": { - "x": 0, - "y": 0, - "w": 82, - "h": 72 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:02eb46aa66ac70df612e129b7801a85c:a77cca14b23f4f3aece64d1a82449a0f:d60cc2e5ae2bd18de8ee3ab0649593ee$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/6706_2.png b/public/images/pokemon/variant/6706_2.png deleted file mode 100644 index 7cf1495d1a3..00000000000 Binary files a/public/images/pokemon/variant/6706_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/6706_3.json b/public/images/pokemon/variant/6706_3.json deleted file mode 100644 index 615ca90e004..00000000000 --- a/public/images/pokemon/variant/6706_3.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "textures": [ - { - "image": "6706_3.png", - "format": "RGBA8888", - "size": { - "w": 82, - "h": 82 - }, - "scale": 1, - "frames": [ - { - "filename": "0001.png", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 82, - "h": 72 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 82, - "h": 72 - }, - "frame": { - "x": 0, - "y": 0, - "w": 82, - "h": 72 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:02eb46aa66ac70df612e129b7801a85c:a77cca14b23f4f3aece64d1a82449a0f:d60cc2e5ae2bd18de8ee3ab0649593ee$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/6706_3.png b/public/images/pokemon/variant/6706_3.png deleted file mode 100644 index 001cab641f1..00000000000 Binary files a/public/images/pokemon/variant/6706_3.png and /dev/null differ diff --git a/public/images/pokemon/variant/_masterlist.json b/public/images/pokemon/variant/_masterlist.json index a93fd220b1f..60ef635b862 100644 --- a/public/images/pokemon/variant/_masterlist.json +++ b/public/images/pokemon/variant/_masterlist.json @@ -3721,8 +3721,8 @@ ], "6706": [ 0, - 2, - 2 + 1, + 1 ], "6713": [ 0, @@ -7754,8 +7754,8 @@ ], "6706": [ 0, - 2, - 2 + 1, + 1 ], "6713": [ 0, @@ -8493,8 +8493,8 @@ ], "705": [ 0, - 2, - 2 + 1, + 1 ], "706": [ 0, @@ -9568,8 +9568,8 @@ ], "6706": [ 0, - 2, - 2 + 1, + 1 ], "female": {}, "back": { @@ -11095,8 +11095,8 @@ ], "6706": [ 0, - 2, - 2 + 1, + 1 ], "6713": [ 0, diff --git a/public/images/pokemon/variant/back/6706.json b/public/images/pokemon/variant/back/6706.json new file mode 100644 index 00000000000..2de5352e936 --- /dev/null +++ b/public/images/pokemon/variant/back/6706.json @@ -0,0 +1,38 @@ +{ + "1": { + "566678": "197497", + "8e96aa": "3b235c", + "929aad": "3aa8c4", + "625287": "4e4094", + "536273": "301848", + "988b98": "b24c86", + "36404c": "0c5474", + "c4cce1": "513981", + "e6d3e9": "f1a4c5", + "bfacc1": "d074a0", + "546475": "0e6296", + "c5cee3": "63cee1", + "80737f": "8a2166", + "4b454f": "6f1357", + "9170b9": "8b69c3", + "b791f2": "c7a1e5" + }, + "2": { + "566678": "a34205", + "8e96aa": "073338", + "929aad": "d27e26", + "625287": "0e3f47", + "536273": "042329", + "988b98": "2b736f", + "36404c": "842401", + "c4cce1": "0d484a", + "e6d3e9": "9cead8", + "bfacc1": "5db6a9", + "546475": "8e480b", + "c5cee3": "f7af58", + "80737f": "194f51", + "4b454f": "274159", + "9170b9": "2f667c", + "b791f2": "4a9699" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/6706_2.json b/public/images/pokemon/variant/back/6706_2.json deleted file mode 100644 index dccfbce60c5..00000000000 --- a/public/images/pokemon/variant/back/6706_2.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "textures": [ - { - "image": "6706_2.png", - "format": "RGBA8888", - "size": { - "w": 79, - "h": 79 - }, - "scale": 1, - "frames": [ - { - "filename": "0001.png", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 79, - "h": 73 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 79, - "h": 73 - }, - "frame": { - "x": 0, - "y": 0, - "w": 79, - "h": 73 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:64f7e6dfa489012922487e45ba53d557:4d24652b372939abe499497c4b6647b0:d60cc2e5ae2bd18de8ee3ab0649593ee$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/6706_2.png b/public/images/pokemon/variant/back/6706_2.png deleted file mode 100644 index e52f1af4ba5..00000000000 Binary files a/public/images/pokemon/variant/back/6706_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/back/6706_3.json b/public/images/pokemon/variant/back/6706_3.json deleted file mode 100644 index 9a97ce27059..00000000000 --- a/public/images/pokemon/variant/back/6706_3.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "textures": [ - { - "image": "6706_3.png", - "format": "RGBA8888", - "size": { - "w": 79, - "h": 79 - }, - "scale": 1, - "frames": [ - { - "filename": "0001.png", - "rotated": false, - "trimmed": false, - "sourceSize": { - "w": 79, - "h": 73 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 79, - "h": 73 - }, - "frame": { - "x": 0, - "y": 0, - "w": 79, - "h": 73 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:64f7e6dfa489012922487e45ba53d557:4d24652b372939abe499497c4b6647b0:d60cc2e5ae2bd18de8ee3ab0649593ee$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/6706_3.png b/public/images/pokemon/variant/back/6706_3.png deleted file mode 100644 index fb780d01499..00000000000 Binary files a/public/images/pokemon/variant/back/6706_3.png and /dev/null differ diff --git a/public/images/pokemon/variant/exp/6706.json b/public/images/pokemon/variant/exp/6706.json new file mode 100644 index 00000000000..2a5f8e112ee --- /dev/null +++ b/public/images/pokemon/variant/exp/6706.json @@ -0,0 +1,40 @@ +{ + "1": { + "566678": "0e6296", + "e0e4f4": "513981", + "625287": "4e4094", + "536273": "1f1233", + "988b98": "b24c86", + "36404c": "0c5474", + "c4cce1": "3b235c", + "e6d3e9": "f1a4c5", + "bfacc1": "da75a5", + "515f70": "197497", + "c5cee3": "63cee1", + "b791f2": "c7a1e5", + "8b93a6": "3aa8c4", + "80737f": "8a2166", + "4b454f": "6f1357", + "9170b9": "8b69c3", + "8e96aa": "301848" + }, + "2": { + "566678": "8e480b", + "e0e4f4": "176463", + "625287": "274159", + "536273": "02262c", + "988b98": "2a6563", + "36404c": "842401", + "c4cce1": "0d484a", + "e6d3e9": "9cead8", + "bfacc1": "5db6a9", + "515f70": "a34205", + "c5cee3": "f7af58", + "b791f2": "4a9699", + "8b93a6": "d27e26", + "80737f": "2b736f", + "4b454f": "194f51", + "9170b9": "2f667c", + "8e96aa": "073338" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/exp/6706_2.json b/public/images/pokemon/variant/exp/6706_2.json deleted file mode 100644 index cb2ddfb1a12..00000000000 --- a/public/images/pokemon/variant/exp/6706_2.json +++ /dev/null @@ -1,2015 +0,0 @@ -{ - "textures": [ - { - "image": "6706_2.png", - "format": "RGBA8888", - "size": { - "w": 508, - "h": 508 - }, - "scale": 1, - "frames": [ - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 28, - "y": 26, - "w": 59, - "h": 61 - }, - "frame": { - "x": 0, - "y": 0, - "w": 59, - "h": 61 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 26, - "y": 25, - "w": 56, - "h": 63 - }, - "frame": { - "x": 59, - "y": 0, - "w": 56, - "h": 63 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 26, - "y": 25, - "w": 56, - "h": 63 - }, - "frame": { - "x": 59, - "y": 0, - "w": 56, - "h": 63 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 28, - "y": 21, - "w": 53, - "h": 65 - }, - "frame": { - "x": 115, - "y": 0, - "w": 53, - "h": 65 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 28, - "y": 21, - "w": 53, - "h": 65 - }, - "frame": { - "x": 115, - "y": 0, - "w": 53, - "h": 65 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 29, - "y": 21, - "w": 54, - "h": 65 - }, - "frame": { - "x": 168, - "y": 0, - "w": 54, - "h": 65 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 29, - "y": 21, - "w": 54, - "h": 65 - }, - "frame": { - "x": 168, - "y": 0, - "w": 54, - "h": 65 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 28, - "y": 21, - "w": 53, - "h": 65 - }, - "frame": { - "x": 222, - "y": 0, - "w": 53, - "h": 65 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 28, - "y": 21, - "w": 53, - "h": 65 - }, - "frame": { - "x": 222, - "y": 0, - "w": 53, - "h": 65 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 25, - "y": 21, - "w": 55, - "h": 66 - }, - "frame": { - "x": 275, - "y": 0, - "w": 55, - "h": 66 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 25, - "y": 21, - "w": 55, - "h": 66 - }, - "frame": { - "x": 275, - "y": 0, - "w": 55, - "h": 66 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 23, - "y": 23, - "w": 54, - "h": 66 - }, - "frame": { - "x": 330, - "y": 0, - "w": 54, - "h": 66 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 23, - "y": 23, - "w": 54, - "h": 66 - }, - "frame": { - "x": 330, - "y": 0, - "w": 54, - "h": 66 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 25, - "y": 21, - "w": 54, - "h": 67 - }, - "frame": { - "x": 384, - "y": 0, - "w": 54, - "h": 67 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 25, - "y": 21, - "w": 54, - "h": 67 - }, - "frame": { - "x": 384, - "y": 0, - "w": 54, - "h": 67 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 23, - "y": 21, - "w": 52, - "h": 68 - }, - "frame": { - "x": 438, - "y": 0, - "w": 52, - "h": 68 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 23, - "y": 21, - "w": 52, - "h": 68 - }, - "frame": { - "x": 438, - "y": 0, - "w": 52, - "h": 68 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 21, - "y": 21, - "w": 53, - "h": 68 - }, - "frame": { - "x": 0, - "y": 61, - "w": 53, - "h": 68 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 21, - "y": 21, - "w": 53, - "h": 68 - }, - "frame": { - "x": 0, - "y": 61, - "w": 53, - "h": 68 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 18, - "y": 22, - "w": 52, - "h": 68 - }, - "frame": { - "x": 53, - "y": 63, - "w": 52, - "h": 68 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 18, - "y": 22, - "w": 52, - "h": 68 - }, - "frame": { - "x": 53, - "y": 63, - "w": 52, - "h": 68 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 19, - "y": 21, - "w": 55, - "h": 69 - }, - "frame": { - "x": 105, - "y": 65, - "w": 55, - "h": 69 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 19, - "y": 21, - "w": 55, - "h": 69 - }, - "frame": { - "x": 105, - "y": 65, - "w": 55, - "h": 69 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 21, - "y": 21, - "w": 53, - "h": 69 - }, - "frame": { - "x": 160, - "y": 65, - "w": 53, - "h": 69 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 21, - "y": 21, - "w": 53, - "h": 69 - }, - "frame": { - "x": 160, - "y": 65, - "w": 53, - "h": 69 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 16, - "y": 21, - "w": 53, - "h": 69 - }, - "frame": { - "x": 213, - "y": 65, - "w": 53, - "h": 69 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 16, - "y": 21, - "w": 53, - "h": 69 - }, - "frame": { - "x": 213, - "y": 65, - "w": 53, - "h": 69 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 15, - "y": 21, - "w": 52, - "h": 70 - }, - "frame": { - "x": 266, - "y": 66, - "w": 52, - "h": 70 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 15, - "y": 21, - "w": 52, - "h": 70 - }, - "frame": { - "x": 266, - "y": 66, - "w": 52, - "h": 70 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 19, - "w": 87, - "h": 71 - }, - "frame": { - "x": 318, - "y": 67, - "w": 87, - "h": 71 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 19, - "w": 87, - "h": 71 - }, - "frame": { - "x": 318, - "y": 67, - "w": 87, - "h": 71 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 19, - "w": 87, - "h": 71 - }, - "frame": { - "x": 318, - "y": 67, - "w": 87, - "h": 71 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 18, - "w": 87, - "h": 71 - }, - "frame": { - "x": 405, - "y": 68, - "w": 87, - "h": 71 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 19, - "w": 86, - "h": 72 - }, - "frame": { - "x": 0, - "y": 131, - "w": 86, - "h": 72 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 19, - "w": 87, - "h": 72 - }, - "frame": { - "x": 86, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 86, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 86, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 19, - "w": 87, - "h": 72 - }, - "frame": { - "x": 173, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 173, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 173, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 260, - "y": 138, - "w": 87, - "h": 72 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 260, - "y": 138, - "w": 87, - "h": 72 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 260, - "y": 138, - "w": 87, - "h": 72 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 347, - "y": 139, - "w": 87, - "h": 72 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 347, - "y": 139, - "w": 87, - "h": 72 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 347, - "y": 139, - "w": 87, - "h": 72 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 74, - "h": 80 - }, - "frame": { - "x": 434, - "y": 139, - "w": 74, - "h": 80 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 74, - "h": 80 - }, - "frame": { - "x": 434, - "y": 139, - "w": 74, - "h": 80 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 85, - "h": 72 - }, - "frame": { - "x": 0, - "y": 203, - "w": 85, - "h": 72 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 13, - "w": 83, - "h": 72 - }, - "frame": { - "x": 85, - "y": 206, - "w": 83, - "h": 72 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 18, - "w": 84, - "h": 73 - }, - "frame": { - "x": 168, - "y": 206, - "w": 84, - "h": 73 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 85, - "h": 73 - }, - "frame": { - "x": 252, - "y": 210, - "w": 85, - "h": 73 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 337, - "y": 211, - "w": 86, - "h": 73 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 337, - "y": 211, - "w": 86, - "h": 73 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 337, - "y": 211, - "w": 86, - "h": 73 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 85, - "h": 73 - }, - "frame": { - "x": 423, - "y": 219, - "w": 85, - "h": 73 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 85, - "h": 73 - }, - "frame": { - "x": 423, - "y": 219, - "w": 85, - "h": 73 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 16, - "w": 85, - "h": 74 - }, - "frame": { - "x": 0, - "y": 275, - "w": 85, - "h": 74 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 16, - "w": 85, - "h": 74 - }, - "frame": { - "x": 0, - "y": 275, - "w": 85, - "h": 74 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 16, - "w": 85, - "h": 74 - }, - "frame": { - "x": 0, - "y": 275, - "w": 85, - "h": 74 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 85, - "y": 279, - "w": 86, - "h": 73 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 85, - "y": 279, - "w": 86, - "h": 73 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 85, - "y": 279, - "w": 86, - "h": 73 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 81, - "h": 74 - }, - "frame": { - "x": 171, - "y": 279, - "w": 81, - "h": 74 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 81, - "h": 74 - }, - "frame": { - "x": 171, - "y": 279, - "w": 81, - "h": 74 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 16, - "w": 84, - "h": 74 - }, - "frame": { - "x": 252, - "y": 283, - "w": 84, - "h": 74 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 16, - "w": 84, - "h": 74 - }, - "frame": { - "x": 252, - "y": 283, - "w": 84, - "h": 74 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 336, - "y": 284, - "w": 86, - "h": 73 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 336, - "y": 284, - "w": 86, - "h": 73 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 80, - "h": 74 - }, - "frame": { - "x": 422, - "y": 292, - "w": 80, - "h": 74 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 80, - "h": 74 - }, - "frame": { - "x": 422, - "y": 292, - "w": 80, - "h": 74 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 74 - }, - "frame": { - "x": 0, - "y": 349, - "w": 79, - "h": 74 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 74 - }, - "frame": { - "x": 0, - "y": 349, - "w": 79, - "h": 74 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 80, - "h": 74 - }, - "frame": { - "x": 79, - "y": 352, - "w": 80, - "h": 74 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 80, - "h": 74 - }, - "frame": { - "x": 79, - "y": 352, - "w": 80, - "h": 74 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 15, - "w": 83, - "h": 75 - }, - "frame": { - "x": 159, - "y": 353, - "w": 83, - "h": 75 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 15, - "w": 83, - "h": 75 - }, - "frame": { - "x": 159, - "y": 353, - "w": 83, - "h": 75 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 15, - "w": 83, - "h": 75 - }, - "frame": { - "x": 159, - "y": 353, - "w": 83, - "h": 75 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 242, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 242, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 242, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 323, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 323, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 323, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 82, - "h": 75 - }, - "frame": { - "x": 404, - "y": 366, - "w": 82, - "h": 75 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 82, - "h": 75 - }, - "frame": { - "x": 404, - "y": 366, - "w": 82, - "h": 75 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 82, - "h": 75 - }, - "frame": { - "x": 404, - "y": 366, - "w": 82, - "h": 75 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 79, - "h": 75 - }, - "frame": { - "x": 0, - "y": 423, - "w": 79, - "h": 75 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 79, - "h": 75 - }, - "frame": { - "x": 0, - "y": 423, - "w": 79, - "h": 75 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 78, - "h": 75 - }, - "frame": { - "x": 79, - "y": 426, - "w": 78, - "h": 75 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 78, - "h": 75 - }, - "frame": { - "x": 79, - "y": 426, - "w": 78, - "h": 75 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 15, - "w": 85, - "h": 75 - }, - "frame": { - "x": 157, - "y": 428, - "w": 85, - "h": 75 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 5, - "y": 14, - "w": 79, - "h": 76 - }, - "frame": { - "x": 242, - "y": 432, - "w": 79, - "h": 76 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 5, - "y": 14, - "w": 79, - "h": 76 - }, - "frame": { - "x": 242, - "y": 432, - "w": 79, - "h": 76 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 5, - "y": 14, - "w": 79, - "h": 76 - }, - "frame": { - "x": 242, - "y": 432, - "w": 79, - "h": 76 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:62a4a665074efb5def1545546995dc5b:de2788ebeab6b42f331926f332da5125:d60cc2e5ae2bd18de8ee3ab0649593ee$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/exp/6706_2.png b/public/images/pokemon/variant/exp/6706_2.png deleted file mode 100644 index 7e7dfa8e05a..00000000000 Binary files a/public/images/pokemon/variant/exp/6706_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/exp/6706_3.json b/public/images/pokemon/variant/exp/6706_3.json deleted file mode 100644 index 8c9b16b80ab..00000000000 --- a/public/images/pokemon/variant/exp/6706_3.json +++ /dev/null @@ -1,2015 +0,0 @@ -{ - "textures": [ - { - "image": "6706_3.png", - "format": "RGBA8888", - "size": { - "w": 508, - "h": 508 - }, - "scale": 1, - "frames": [ - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 28, - "y": 26, - "w": 59, - "h": 61 - }, - "frame": { - "x": 0, - "y": 0, - "w": 59, - "h": 61 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 26, - "y": 25, - "w": 56, - "h": 63 - }, - "frame": { - "x": 59, - "y": 0, - "w": 56, - "h": 63 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 26, - "y": 25, - "w": 56, - "h": 63 - }, - "frame": { - "x": 59, - "y": 0, - "w": 56, - "h": 63 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 28, - "y": 21, - "w": 53, - "h": 65 - }, - "frame": { - "x": 115, - "y": 0, - "w": 53, - "h": 65 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 28, - "y": 21, - "w": 53, - "h": 65 - }, - "frame": { - "x": 115, - "y": 0, - "w": 53, - "h": 65 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 29, - "y": 21, - "w": 54, - "h": 65 - }, - "frame": { - "x": 168, - "y": 0, - "w": 54, - "h": 65 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 29, - "y": 21, - "w": 54, - "h": 65 - }, - "frame": { - "x": 168, - "y": 0, - "w": 54, - "h": 65 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 28, - "y": 21, - "w": 53, - "h": 65 - }, - "frame": { - "x": 222, - "y": 0, - "w": 53, - "h": 65 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 28, - "y": 21, - "w": 53, - "h": 65 - }, - "frame": { - "x": 222, - "y": 0, - "w": 53, - "h": 65 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 25, - "y": 21, - "w": 55, - "h": 66 - }, - "frame": { - "x": 275, - "y": 0, - "w": 55, - "h": 66 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 25, - "y": 21, - "w": 55, - "h": 66 - }, - "frame": { - "x": 275, - "y": 0, - "w": 55, - "h": 66 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 23, - "y": 23, - "w": 54, - "h": 66 - }, - "frame": { - "x": 330, - "y": 0, - "w": 54, - "h": 66 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 23, - "y": 23, - "w": 54, - "h": 66 - }, - "frame": { - "x": 330, - "y": 0, - "w": 54, - "h": 66 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 25, - "y": 21, - "w": 54, - "h": 67 - }, - "frame": { - "x": 384, - "y": 0, - "w": 54, - "h": 67 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 25, - "y": 21, - "w": 54, - "h": 67 - }, - "frame": { - "x": 384, - "y": 0, - "w": 54, - "h": 67 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 23, - "y": 21, - "w": 52, - "h": 68 - }, - "frame": { - "x": 438, - "y": 0, - "w": 52, - "h": 68 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 23, - "y": 21, - "w": 52, - "h": 68 - }, - "frame": { - "x": 438, - "y": 0, - "w": 52, - "h": 68 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 21, - "y": 21, - "w": 53, - "h": 68 - }, - "frame": { - "x": 0, - "y": 61, - "w": 53, - "h": 68 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 21, - "y": 21, - "w": 53, - "h": 68 - }, - "frame": { - "x": 0, - "y": 61, - "w": 53, - "h": 68 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 18, - "y": 22, - "w": 52, - "h": 68 - }, - "frame": { - "x": 53, - "y": 63, - "w": 52, - "h": 68 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 18, - "y": 22, - "w": 52, - "h": 68 - }, - "frame": { - "x": 53, - "y": 63, - "w": 52, - "h": 68 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 19, - "y": 21, - "w": 55, - "h": 69 - }, - "frame": { - "x": 105, - "y": 65, - "w": 55, - "h": 69 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 19, - "y": 21, - "w": 55, - "h": 69 - }, - "frame": { - "x": 105, - "y": 65, - "w": 55, - "h": 69 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 21, - "y": 21, - "w": 53, - "h": 69 - }, - "frame": { - "x": 160, - "y": 65, - "w": 53, - "h": 69 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 21, - "y": 21, - "w": 53, - "h": 69 - }, - "frame": { - "x": 160, - "y": 65, - "w": 53, - "h": 69 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 16, - "y": 21, - "w": 53, - "h": 69 - }, - "frame": { - "x": 213, - "y": 65, - "w": 53, - "h": 69 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 16, - "y": 21, - "w": 53, - "h": 69 - }, - "frame": { - "x": 213, - "y": 65, - "w": 53, - "h": 69 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 15, - "y": 21, - "w": 52, - "h": 70 - }, - "frame": { - "x": 266, - "y": 66, - "w": 52, - "h": 70 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 15, - "y": 21, - "w": 52, - "h": 70 - }, - "frame": { - "x": 266, - "y": 66, - "w": 52, - "h": 70 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 19, - "w": 87, - "h": 71 - }, - "frame": { - "x": 318, - "y": 67, - "w": 87, - "h": 71 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 19, - "w": 87, - "h": 71 - }, - "frame": { - "x": 318, - "y": 67, - "w": 87, - "h": 71 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 19, - "w": 87, - "h": 71 - }, - "frame": { - "x": 318, - "y": 67, - "w": 87, - "h": 71 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 18, - "w": 87, - "h": 71 - }, - "frame": { - "x": 405, - "y": 68, - "w": 87, - "h": 71 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 19, - "w": 86, - "h": 72 - }, - "frame": { - "x": 0, - "y": 131, - "w": 86, - "h": 72 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 19, - "w": 87, - "h": 72 - }, - "frame": { - "x": 86, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 86, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 86, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 19, - "w": 87, - "h": 72 - }, - "frame": { - "x": 173, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 173, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 173, - "y": 134, - "w": 87, - "h": 72 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 260, - "y": 138, - "w": 87, - "h": 72 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 260, - "y": 138, - "w": 87, - "h": 72 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 260, - "y": 138, - "w": 87, - "h": 72 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 347, - "y": 139, - "w": 87, - "h": 72 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 347, - "y": 139, - "w": 87, - "h": 72 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 18, - "w": 87, - "h": 72 - }, - "frame": { - "x": 347, - "y": 139, - "w": 87, - "h": 72 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 74, - "h": 80 - }, - "frame": { - "x": 434, - "y": 139, - "w": 74, - "h": 80 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 74, - "h": 80 - }, - "frame": { - "x": 434, - "y": 139, - "w": 74, - "h": 80 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 85, - "h": 72 - }, - "frame": { - "x": 0, - "y": 203, - "w": 85, - "h": 72 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 13, - "w": 83, - "h": 72 - }, - "frame": { - "x": 85, - "y": 206, - "w": 83, - "h": 72 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 18, - "w": 84, - "h": 73 - }, - "frame": { - "x": 168, - "y": 206, - "w": 84, - "h": 73 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 85, - "h": 73 - }, - "frame": { - "x": 252, - "y": 210, - "w": 85, - "h": 73 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 337, - "y": 211, - "w": 86, - "h": 73 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 337, - "y": 211, - "w": 86, - "h": 73 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 337, - "y": 211, - "w": 86, - "h": 73 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 85, - "h": 73 - }, - "frame": { - "x": 423, - "y": 219, - "w": 85, - "h": 73 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 85, - "h": 73 - }, - "frame": { - "x": 423, - "y": 219, - "w": 85, - "h": 73 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 16, - "w": 85, - "h": 74 - }, - "frame": { - "x": 0, - "y": 275, - "w": 85, - "h": 74 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 16, - "w": 85, - "h": 74 - }, - "frame": { - "x": 0, - "y": 275, - "w": 85, - "h": 74 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 1, - "y": 16, - "w": 85, - "h": 74 - }, - "frame": { - "x": 0, - "y": 275, - "w": 85, - "h": 74 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 85, - "y": 279, - "w": 86, - "h": 73 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 85, - "y": 279, - "w": 86, - "h": 73 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 85, - "y": 279, - "w": 86, - "h": 73 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 81, - "h": 74 - }, - "frame": { - "x": 171, - "y": 279, - "w": 81, - "h": 74 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 4, - "w": 81, - "h": 74 - }, - "frame": { - "x": 171, - "y": 279, - "w": 81, - "h": 74 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 16, - "w": 84, - "h": 74 - }, - "frame": { - "x": 252, - "y": 283, - "w": 84, - "h": 74 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 3, - "y": 16, - "w": 84, - "h": 74 - }, - "frame": { - "x": 252, - "y": 283, - "w": 84, - "h": 74 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 336, - "y": 284, - "w": 86, - "h": 73 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 17, - "w": 86, - "h": 73 - }, - "frame": { - "x": 336, - "y": 284, - "w": 86, - "h": 73 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 80, - "h": 74 - }, - "frame": { - "x": 422, - "y": 292, - "w": 80, - "h": 74 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 80, - "h": 74 - }, - "frame": { - "x": 422, - "y": 292, - "w": 80, - "h": 74 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 74 - }, - "frame": { - "x": 0, - "y": 349, - "w": 79, - "h": 74 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 79, - "h": 74 - }, - "frame": { - "x": 0, - "y": 349, - "w": 79, - "h": 74 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 80, - "h": 74 - }, - "frame": { - "x": 79, - "y": 352, - "w": 80, - "h": 74 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 80, - "h": 74 - }, - "frame": { - "x": 79, - "y": 352, - "w": 80, - "h": 74 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 15, - "w": 83, - "h": 75 - }, - "frame": { - "x": 159, - "y": 353, - "w": 83, - "h": 75 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 15, - "w": 83, - "h": 75 - }, - "frame": { - "x": 159, - "y": 353, - "w": 83, - "h": 75 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 15, - "w": 83, - "h": 75 - }, - "frame": { - "x": 159, - "y": 353, - "w": 83, - "h": 75 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 242, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 242, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 242, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 323, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 323, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 81, - "h": 75 - }, - "frame": { - "x": 323, - "y": 357, - "w": 81, - "h": 75 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 82, - "h": 75 - }, - "frame": { - "x": 404, - "y": 366, - "w": 82, - "h": 75 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 82, - "h": 75 - }, - "frame": { - "x": 404, - "y": 366, - "w": 82, - "h": 75 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 4, - "y": 15, - "w": 82, - "h": 75 - }, - "frame": { - "x": 404, - "y": 366, - "w": 82, - "h": 75 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 79, - "h": 75 - }, - "frame": { - "x": 0, - "y": 423, - "w": 79, - "h": 75 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 79, - "h": 75 - }, - "frame": { - "x": 0, - "y": 423, - "w": 79, - "h": 75 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 78, - "h": 75 - }, - "frame": { - "x": 79, - "y": 426, - "w": 78, - "h": 75 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 78, - "h": 75 - }, - "frame": { - "x": 79, - "y": 426, - "w": 78, - "h": 75 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 2, - "y": 15, - "w": 85, - "h": 75 - }, - "frame": { - "x": 157, - "y": 428, - "w": 85, - "h": 75 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 5, - "y": 14, - "w": 79, - "h": 76 - }, - "frame": { - "x": 242, - "y": 432, - "w": 79, - "h": 76 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 5, - "y": 14, - "w": 79, - "h": 76 - }, - "frame": { - "x": 242, - "y": 432, - "w": 79, - "h": 76 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 88, - "h": 91 - }, - "spriteSourceSize": { - "x": 5, - "y": 14, - "w": 79, - "h": 76 - }, - "frame": { - "x": 242, - "y": 432, - "w": 79, - "h": 76 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:62a4a665074efb5def1545546995dc5b:de2788ebeab6b42f331926f332da5125:d60cc2e5ae2bd18de8ee3ab0649593ee$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/exp/6706_3.png b/public/images/pokemon/variant/exp/6706_3.png deleted file mode 100644 index 3ad44f4bbf5..00000000000 Binary files a/public/images/pokemon/variant/exp/6706_3.png and /dev/null differ diff --git a/public/images/pokemon/variant/exp/705.json b/public/images/pokemon/variant/exp/705.json new file mode 100644 index 00000000000..a29b8f124dc --- /dev/null +++ b/public/images/pokemon/variant/exp/705.json @@ -0,0 +1,33 @@ +{ + "1": { + "101010":"101010", + "4d454d":"8a2166", + "807380":"b93f84", + "bfacbf":"e56ca6", + "f2daf2":"fbb3d2", + "665980":"4e4094", + "8f7db3":"8b69c3", + "b8a1e5":"c7a1e5", + "4d993d":"aa6a00", + "66cc52":"ffd047", + "4e9c3e":"0c5474", + "67cf53":"3aa8c4", + "b6f2aa":"63cee1" + }, + "2": { + "101010":"101010", + "4d454d":"194f51", + "807380":"2b736f", + "bfacbf":"5db6a9", + "f2daf2":"9cead8", + "665980":"274159", + "8f7db3":"2f667c", + "b8a1e5":"4a9699", + "4d993d":"007d61", + "66cc52":"49ffbf", + "4e9c3e":"842401", + "67cf53":"a34205", + "b6f2aa":"d27e26" + } +} + diff --git a/public/images/pokemon/variant/exp/705_2.json b/public/images/pokemon/variant/exp/705_2.json deleted file mode 100644 index bf9fd104c5d..00000000000 --- a/public/images/pokemon/variant/exp/705_2.json +++ /dev/null @@ -1,272 +0,0 @@ -{ - "textures": [ - { - "image": "705_2.png", - "format": "RGBA8888", - "size": { - "w": 154, - "h": 154 - }, - "scale": 1, - "frames": [ - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 46, - "h": 58 - }, - "frame": { - "x": 0, - "y": 0, - "w": 46, - "h": 58 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 46, - "h": 58 - }, - "frame": { - "x": 0, - "y": 0, - "w": 46, - "h": 58 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 45, - "h": 58 - }, - "frame": { - "x": 46, - "y": 0, - "w": 45, - "h": 58 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 45, - "h": 58 - }, - "frame": { - "x": 46, - "y": 0, - "w": 45, - "h": 58 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 45, - "h": 58 - }, - "frame": { - "x": 91, - "y": 0, - "w": 45, - "h": 58 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 42, - "h": 58 - }, - "frame": { - "x": 0, - "y": 58, - "w": 42, - "h": 58 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 42, - "h": 58 - }, - "frame": { - "x": 0, - "y": 58, - "w": 42, - "h": 58 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 41, - "h": 58 - }, - "frame": { - "x": 42, - "y": 58, - "w": 41, - "h": 58 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 41, - "h": 58 - }, - "frame": { - "x": 42, - "y": 58, - "w": 41, - "h": 58 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 36, - "h": 58 - }, - "frame": { - "x": 83, - "y": 58, - "w": 36, - "h": 58 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 36, - "h": 58 - }, - "frame": { - "x": 83, - "y": 58, - "w": 36, - "h": 58 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 35, - "h": 58 - }, - "frame": { - "x": 119, - "y": 58, - "w": 35, - "h": 58 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:4bf155254b23c88780e7eee282256589:82bb727988054c3064e203b6908ff464:6b57e983626c7fc9144ab67f30c66814$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/exp/705_2.png b/public/images/pokemon/variant/exp/705_2.png deleted file mode 100644 index 8256ebc7fdb..00000000000 Binary files a/public/images/pokemon/variant/exp/705_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/exp/705_3.json b/public/images/pokemon/variant/exp/705_3.json deleted file mode 100644 index 199d7bc9c3e..00000000000 --- a/public/images/pokemon/variant/exp/705_3.json +++ /dev/null @@ -1,272 +0,0 @@ -{ - "textures": [ - { - "image": "705_3.png", - "format": "RGBA8888", - "size": { - "w": 154, - "h": 154 - }, - "scale": 1, - "frames": [ - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 46, - "h": 58 - }, - "frame": { - "x": 0, - "y": 0, - "w": 46, - "h": 58 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 46, - "h": 58 - }, - "frame": { - "x": 0, - "y": 0, - "w": 46, - "h": 58 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 45, - "h": 58 - }, - "frame": { - "x": 46, - "y": 0, - "w": 45, - "h": 58 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 45, - "h": 58 - }, - "frame": { - "x": 46, - "y": 0, - "w": 45, - "h": 58 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 45, - "h": 58 - }, - "frame": { - "x": 91, - "y": 0, - "w": 45, - "h": 58 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 42, - "h": 58 - }, - "frame": { - "x": 0, - "y": 58, - "w": 42, - "h": 58 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 42, - "h": 58 - }, - "frame": { - "x": 0, - "y": 58, - "w": 42, - "h": 58 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 41, - "h": 58 - }, - "frame": { - "x": 42, - "y": 58, - "w": 41, - "h": 58 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 41, - "h": 58 - }, - "frame": { - "x": 42, - "y": 58, - "w": 41, - "h": 58 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 36, - "h": 58 - }, - "frame": { - "x": 83, - "y": 58, - "w": 36, - "h": 58 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 36, - "h": 58 - }, - "frame": { - "x": 83, - "y": 58, - "w": 36, - "h": 58 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 49, - "h": 58 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 35, - "h": 58 - }, - "frame": { - "x": 119, - "y": 58, - "w": 35, - "h": 58 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:4bf155254b23c88780e7eee282256589:82bb727988054c3064e203b6908ff464:6b57e983626c7fc9144ab67f30c66814$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/exp/705_3.png b/public/images/pokemon/variant/exp/705_3.png deleted file mode 100644 index 66b43956bdf..00000000000 Binary files a/public/images/pokemon/variant/exp/705_3.png and /dev/null differ diff --git a/public/images/pokemon/variant/exp/back/6706.json b/public/images/pokemon/variant/exp/back/6706.json new file mode 100644 index 00000000000..2de5352e936 --- /dev/null +++ b/public/images/pokemon/variant/exp/back/6706.json @@ -0,0 +1,38 @@ +{ + "1": { + "566678": "197497", + "8e96aa": "3b235c", + "929aad": "3aa8c4", + "625287": "4e4094", + "536273": "301848", + "988b98": "b24c86", + "36404c": "0c5474", + "c4cce1": "513981", + "e6d3e9": "f1a4c5", + "bfacc1": "d074a0", + "546475": "0e6296", + "c5cee3": "63cee1", + "80737f": "8a2166", + "4b454f": "6f1357", + "9170b9": "8b69c3", + "b791f2": "c7a1e5" + }, + "2": { + "566678": "a34205", + "8e96aa": "073338", + "929aad": "d27e26", + "625287": "0e3f47", + "536273": "042329", + "988b98": "2b736f", + "36404c": "842401", + "c4cce1": "0d484a", + "e6d3e9": "9cead8", + "bfacc1": "5db6a9", + "546475": "8e480b", + "c5cee3": "f7af58", + "80737f": "194f51", + "4b454f": "274159", + "9170b9": "2f667c", + "b791f2": "4a9699" + } +} \ No newline at end of file diff --git a/public/images/pokemon/variant/exp/back/6706_2.json b/public/images/pokemon/variant/exp/back/6706_2.json deleted file mode 100644 index 5c916aeb664..00000000000 --- a/public/images/pokemon/variant/exp/back/6706_2.json +++ /dev/null @@ -1,776 +0,0 @@ -{ - "textures": [ - { - "image": "6706_2.png", - "format": "RGBA8888", - "size": { - "w": 358, - "h": 358 - }, - "scale": 1, - "frames": [ - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 84, - "h": 69 - }, - "frame": { - "x": 0, - "y": 0, - "w": 84, - "h": 69 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 84, - "h": 69 - }, - "frame": { - "x": 0, - "y": 0, - "w": 84, - "h": 69 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 1, - "w": 83, - "h": 72 - }, - "frame": { - "x": 84, - "y": 0, - "w": 83, - "h": 72 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 1, - "w": 83, - "h": 72 - }, - "frame": { - "x": 84, - "y": 0, - "w": 83, - "h": 72 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 1, - "w": 83, - "h": 72 - }, - "frame": { - "x": 0, - "y": 69, - "w": 83, - "h": 72 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 83, - "h": 70 - }, - "frame": { - "x": 167, - "y": 0, - "w": 83, - "h": 70 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 83, - "h": 70 - }, - "frame": { - "x": 167, - "y": 0, - "w": 83, - "h": 70 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 83, - "h": 70 - }, - "frame": { - "x": 250, - "y": 0, - "w": 83, - "h": 70 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 83, - "h": 70 - }, - "frame": { - "x": 250, - "y": 0, - "w": 83, - "h": 70 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 167, - "y": 70, - "w": 82, - "h": 73 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 167, - "y": 70, - "w": 82, - "h": 73 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 83, - "y": 72, - "w": 82, - "h": 73 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 83, - "y": 72, - "w": 82, - "h": 73 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 0, - "y": 141, - "w": 82, - "h": 73 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 0, - "y": 141, - "w": 82, - "h": 73 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 0, - "y": 141, - "w": 82, - "h": 73 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 249, - "y": 70, - "w": 82, - "h": 73 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 249, - "y": 70, - "w": 82, - "h": 73 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 81, - "h": 73 - }, - "frame": { - "x": 0, - "y": 214, - "w": 81, - "h": 73 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 81, - "h": 73 - }, - "frame": { - "x": 0, - "y": 214, - "w": 81, - "h": 73 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 81, - "h": 71 - }, - "frame": { - "x": 0, - "y": 287, - "w": 81, - "h": 71 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 81, - "h": 71 - }, - "frame": { - "x": 0, - "y": 287, - "w": 81, - "h": 71 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 81, - "h": 73 - }, - "frame": { - "x": 81, - "y": 214, - "w": 81, - "h": 73 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 81, - "h": 73 - }, - "frame": { - "x": 81, - "y": 214, - "w": 81, - "h": 73 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 81, - "h": 71 - }, - "frame": { - "x": 81, - "y": 287, - "w": 81, - "h": 71 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 81, - "h": 71 - }, - "frame": { - "x": 81, - "y": 287, - "w": 81, - "h": 71 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 82, - "h": 72 - }, - "frame": { - "x": 165, - "y": 143, - "w": 82, - "h": 72 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 82, - "h": 72 - }, - "frame": { - "x": 165, - "y": 143, - "w": 82, - "h": 72 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 82, - "h": 72 - }, - "frame": { - "x": 247, - "y": 143, - "w": 82, - "h": 72 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 82, - "h": 72 - }, - "frame": { - "x": 247, - "y": 143, - "w": 82, - "h": 72 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 80, - "h": 73 - }, - "frame": { - "x": 162, - "y": 215, - "w": 80, - "h": 73 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 80, - "h": 73 - }, - "frame": { - "x": 162, - "y": 215, - "w": 80, - "h": 73 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 288, - "w": 81, - "h": 70 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 288, - "w": 81, - "h": 70 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 80, - "h": 73 - }, - "frame": { - "x": 242, - "y": 215, - "w": 80, - "h": 73 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 80, - "h": 73 - }, - "frame": { - "x": 242, - "y": 215, - "w": 80, - "h": 73 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:5d65e2c5a6a97b7c7014a175ce3592af:3255e87f637a475d82734fc7d93baf71:d60cc2e5ae2bd18de8ee3ab0649593ee$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/exp/back/6706_2.png b/public/images/pokemon/variant/exp/back/6706_2.png deleted file mode 100644 index cb793478420..00000000000 Binary files a/public/images/pokemon/variant/exp/back/6706_2.png and /dev/null differ diff --git a/public/images/pokemon/variant/exp/back/6706_3.json b/public/images/pokemon/variant/exp/back/6706_3.json deleted file mode 100644 index 3bb1dc426b2..00000000000 --- a/public/images/pokemon/variant/exp/back/6706_3.json +++ /dev/null @@ -1,776 +0,0 @@ -{ - "textures": [ - { - "image": "6706_3.png", - "format": "RGBA8888", - "size": { - "w": 358, - "h": 358 - }, - "scale": 1, - "frames": [ - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 84, - "h": 69 - }, - "frame": { - "x": 0, - "y": 0, - "w": 84, - "h": 69 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 0, - "y": 4, - "w": 84, - "h": 69 - }, - "frame": { - "x": 0, - "y": 0, - "w": 84, - "h": 69 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 1, - "w": 83, - "h": 72 - }, - "frame": { - "x": 84, - "y": 0, - "w": 83, - "h": 72 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 1, - "w": 83, - "h": 72 - }, - "frame": { - "x": 84, - "y": 0, - "w": 83, - "h": 72 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 1, - "w": 83, - "h": 72 - }, - "frame": { - "x": 0, - "y": 69, - "w": 83, - "h": 72 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 83, - "h": 70 - }, - "frame": { - "x": 167, - "y": 0, - "w": 83, - "h": 70 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 83, - "h": 70 - }, - "frame": { - "x": 167, - "y": 0, - "w": 83, - "h": 70 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 83, - "h": 70 - }, - "frame": { - "x": 250, - "y": 0, - "w": 83, - "h": 70 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 3, - "w": 83, - "h": 70 - }, - "frame": { - "x": 250, - "y": 0, - "w": 83, - "h": 70 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 167, - "y": 70, - "w": 82, - "h": 73 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 167, - "y": 70, - "w": 82, - "h": 73 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 83, - "y": 72, - "w": 82, - "h": 73 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 83, - "y": 72, - "w": 82, - "h": 73 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 0, - "y": 141, - "w": 82, - "h": 73 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 0, - "y": 141, - "w": 82, - "h": 73 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 0, - "y": 141, - "w": 82, - "h": 73 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 249, - "y": 70, - "w": 82, - "h": 73 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 4, - "y": 0, - "w": 82, - "h": 73 - }, - "frame": { - "x": 249, - "y": 70, - "w": 82, - "h": 73 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 81, - "h": 73 - }, - "frame": { - "x": 0, - "y": 214, - "w": 81, - "h": 73 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 81, - "h": 73 - }, - "frame": { - "x": 0, - "y": 214, - "w": 81, - "h": 73 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 81, - "h": 71 - }, - "frame": { - "x": 0, - "y": 287, - "w": 81, - "h": 71 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 81, - "h": 71 - }, - "frame": { - "x": 0, - "y": 287, - "w": 81, - "h": 71 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 81, - "h": 73 - }, - "frame": { - "x": 81, - "y": 214, - "w": 81, - "h": 73 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 5, - "y": 0, - "w": 81, - "h": 73 - }, - "frame": { - "x": 81, - "y": 214, - "w": 81, - "h": 73 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 81, - "h": 71 - }, - "frame": { - "x": 81, - "y": 287, - "w": 81, - "h": 71 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 1, - "y": 2, - "w": 81, - "h": 71 - }, - "frame": { - "x": 81, - "y": 287, - "w": 81, - "h": 71 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 82, - "h": 72 - }, - "frame": { - "x": 165, - "y": 143, - "w": 82, - "h": 72 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 82, - "h": 72 - }, - "frame": { - "x": 165, - "y": 143, - "w": 82, - "h": 72 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 82, - "h": 72 - }, - "frame": { - "x": 247, - "y": 143, - "w": 82, - "h": 72 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 2, - "y": 1, - "w": 82, - "h": 72 - }, - "frame": { - "x": 247, - "y": 143, - "w": 82, - "h": 72 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 80, - "h": 73 - }, - "frame": { - "x": 162, - "y": 215, - "w": 80, - "h": 73 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 80, - "h": 73 - }, - "frame": { - "x": 162, - "y": 215, - "w": 80, - "h": 73 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 288, - "w": 81, - "h": 70 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 81, - "h": 70 - }, - "frame": { - "x": 162, - "y": 288, - "w": 81, - "h": 70 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 80, - "h": 73 - }, - "frame": { - "x": 242, - "y": 215, - "w": 80, - "h": 73 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 86, - "h": 73 - }, - "spriteSourceSize": { - "x": 6, - "y": 0, - "w": 80, - "h": 73 - }, - "frame": { - "x": 242, - "y": 215, - "w": 80, - "h": 73 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:5d65e2c5a6a97b7c7014a175ce3592af:3255e87f637a475d82734fc7d93baf71:d60cc2e5ae2bd18de8ee3ab0649593ee$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/exp/back/6706_3.png b/public/images/pokemon/variant/exp/back/6706_3.png deleted file mode 100644 index 6390c20799f..00000000000 Binary files a/public/images/pokemon/variant/exp/back/6706_3.png and /dev/null differ diff --git a/public/images/pokemon_icons_9v.json b/public/images/pokemon_icons_9v.json index 83a47f101fa..06909a8298f 100644 --- a/public/images/pokemon_icons_9v.json +++ b/public/images/pokemon_icons_9v.json @@ -853,14 +853,14 @@ "spriteSourceSize": { "x": 7, "y": 2, "w": 27, "h": 26 }, "sourceSize": { "w": 40, "h": 30 } }, - "981_2.png": { + "981_2": { "frame": { "x": 108, "y": 87, "w": 23, "h": 30 }, "rotated": false, "trimmed": true, "spriteSourceSize": { "x": 9, "y": 0, "w": 23, "h": 30 }, "sourceSize": { "w": 40, "h": 30 } }, - "981_3.png": { + "981_3": { "frame": { "x": 246, "y": 86, "w": 23, "h": 30 }, "rotated": false, "trimmed": true, diff --git a/public/images/statuses_it.png b/public/images/statuses_it.png index d372b989be9..af3107018f8 100644 Binary files a/public/images/statuses_it.png and b/public/images/statuses_it.png differ diff --git a/public/images/types_it.png b/public/images/types_it.png index 8b644f1041c..3be03aeea68 100644 Binary files a/public/images/types_it.png and b/public/images/types_it.png differ diff --git a/public/locales b/public/locales index 005989574fe..3ccef8472dd 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit 005989574fe5638897fa2933b6f57ae4b9c83635 +Subproject commit 3ccef8472dd7cc7c362538489954cb8fdad27e5f diff --git a/src/account.ts b/src/account.ts index c6d2f85489a..692ff2b0d81 100644 --- a/src/account.ts +++ b/src/account.ts @@ -20,7 +20,7 @@ export function initLoggedInUser(): void { export function updateUserInfo(): Promise<[boolean, integer]> { return new Promise<[boolean, integer]>(resolve => { if (bypassLogin) { - loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "", hasAdminRole: false}; + loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "", hasAdminRole: false }; let lastSessionSlot = -1; for (let s = 0; s < 5; s++) { if (localStorage.getItem(`sessionData${s ? s : ""}_${loggedInUser.username}`)) { diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 1bb0d6bfc4b..0d482a5f1a5 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1,57 +1,57 @@ import Phaser from "phaser"; -import UI from "./ui/ui"; -import Pokemon, { EnemyPokemon, PlayerPokemon } from "./field/pokemon"; -import PokemonSpecies, { allSpecies, getPokemonSpecies, PokemonSpeciesFilter } from "./data/pokemon-species"; +import UI from "#app/ui/ui"; +import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; +import PokemonSpecies, { allSpecies, getPokemonSpecies, PokemonSpeciesFilter } from "#app/data/pokemon-species"; import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils"; -import * as Utils from "./utils"; -import { ConsumableModifier, ConsumablePokemonModifier, DoubleBattleChanceBoosterModifier, ExpBalanceModifier, ExpShareModifier, FusePokemonModifier, HealingBoosterModifier, Modifier, ModifierBar, ModifierPredicate, MultipleParticipantExpBonusModifier, overrideHeldItems, overrideModifiers, PersistentModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, TerastallizeModifier, TurnHeldItemTransferModifier } from "./modifier/modifier"; -import { PokeballType } from "./data/pokeball"; -import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "./data/battle-anims"; -import { Phase } from "./phase"; -import { initGameSpeed } from "./system/game-speed"; -import { Arena, ArenaBase } from "./field/arena"; -import { GameData } from "./system/game-data"; -import { addTextObject, getTextColor, TextStyle } from "./ui/text"; -import { allMoves } from "./data/move"; -import { getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getModifierType, getPartyLuckValue, ModifierPoolType, modifierTypes, PokemonHeldItemModifierType } from "./modifier/modifier-type"; -import AbilityBar from "./ui/ability-bar"; -import { allAbilities, applyAbAttrs, applyPostBattleInitAbAttrs, BlockItemTheftAbAttr, ChangeMovePriorityAbAttr, DoubleBattleChanceAbAttr, PostBattleInitAbAttr } from "./data/ability"; -import Battle, { BattleType, FixedBattleConfig } from "./battle"; -import { GameMode, GameModes, getGameMode } from "./game-mode"; -import FieldSpritePipeline from "./pipelines/field-sprite"; -import SpritePipeline from "./pipelines/sprite"; -import PartyExpBar from "./ui/party-exp-bar"; -import { trainerConfigs, TrainerSlot } from "./data/trainer-config"; -import Trainer, { TrainerVariant } from "./field/trainer"; -import TrainerData from "./system/trainer-data"; +import * as Utils from "#app/utils"; +import { ConsumableModifier, ConsumablePokemonModifier, DoubleBattleChanceBoosterModifier, ExpBalanceModifier, ExpShareModifier, FusePokemonModifier, HealingBoosterModifier, Modifier, ModifierBar, ModifierPredicate, MultipleParticipantExpBonusModifier, overrideHeldItems, overrideModifiers, PersistentModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, RememberMoveModifier, TerastallizeModifier, TurnHeldItemTransferModifier } from "./modifier/modifier"; +import { PokeballType } from "#app/data/pokeball"; +import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "#app/data/battle-anims"; +import { Phase } from "#app/phase"; +import { initGameSpeed } from "#app/system/game-speed"; +import { Arena, ArenaBase } from "#app/field/arena"; +import { GameData } from "#app/system/game-data"; +import { addTextObject, getTextColor, TextStyle } from "#app/ui/text"; +import { allMoves } from "#app/data/move"; +import { getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getModifierType, getPartyLuckValue, ModifierPoolType, modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; +import AbilityBar from "#app/ui/ability-bar"; +import { allAbilities, applyAbAttrs, applyPostBattleInitAbAttrs, BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, PostBattleInitAbAttr } from "#app/data/ability"; +import Battle, { BattleType, FixedBattleConfig } from "#app/battle"; +import { GameMode, GameModes, getGameMode } from "#app/game-mode"; +import FieldSpritePipeline from "#app/pipelines/field-sprite"; +import SpritePipeline from "#app/pipelines/sprite"; +import PartyExpBar from "#app/ui/party-exp-bar"; +import { trainerConfigs, TrainerSlot } from "#app/data/trainer-config"; +import Trainer, { TrainerVariant } from "#app/field/trainer"; +import TrainerData from "#app/system/trainer-data"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; -import { pokemonPrevolutions } from "./data/balance/pokemon-evolutions"; -import PokeballTray from "./ui/pokeball-tray"; -import InvertPostFX from "./pipelines/invert"; -import { Achv, achvs, ModifierAchv, MoneyAchv } from "./system/achv"; -import { Voucher, vouchers } from "./system/voucher"; -import { Gender } from "./data/gender"; +import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; +import PokeballTray from "#app/ui/pokeball-tray"; +import InvertPostFX from "#app/pipelines/invert"; +import { Achv, achvs, ModifierAchv, MoneyAchv } from "#app/system/achv"; +import { Voucher, vouchers } from "#app/system/voucher"; +import { Gender } from "#app/data/gender"; import UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin"; -import { addUiThemeOverrides } from "./ui/ui-theme"; -import PokemonData from "./system/pokemon-data"; -import { Nature } from "./data/nature"; -import { FormChangeItem, pokemonFormChanges, SpeciesFormChange, SpeciesFormChangeManualTrigger, SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger } from "./data/pokemon-forms"; -import { FormChangePhase } from "./phases/form-change-phase"; -import { getTypeRgb } from "./data/type"; -import PokemonSpriteSparkleHandler from "./field/pokemon-sprite-sparkle-handler"; -import CharSprite from "./ui/char-sprite"; -import DamageNumberHandler from "./field/damage-number-handler"; -import PokemonInfoContainer from "./ui/pokemon-info-container"; -import { biomeDepths, getBiomeName } from "./data/balance/biomes"; -import { SceneBase } from "./scene-base"; -import CandyBar from "./ui/candy-bar"; -import { Variant, variantData } from "./data/variant"; +import { addUiThemeOverrides } from "#app/ui/ui-theme"; +import PokemonData from "#app/system/pokemon-data"; +import { Nature } from "#app/data/nature"; +import { FormChangeItem, pokemonFormChanges, SpeciesFormChange, SpeciesFormChangeManualTrigger, SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger } from "#app/data/pokemon-forms"; +import { FormChangePhase } from "#app/phases/form-change-phase"; +import { getTypeRgb } from "#app/data/type"; +import PokemonSpriteSparkleHandler from "#app/field/pokemon-sprite-sparkle-handler"; +import CharSprite from "#app/ui/char-sprite"; +import DamageNumberHandler from "#app/field/damage-number-handler"; +import PokemonInfoContainer from "#app/ui/pokemon-info-container"; +import { biomeDepths, getBiomeName } from "#app/data/balance/biomes"; +import { SceneBase } from "#app/scene-base"; +import CandyBar from "#app/ui/candy-bar"; +import { Variant, variantData } from "#app/data/variant"; import { Localizable } from "#app/interfaces/locales"; import Overrides from "#app/overrides"; -import { InputsController } from "./inputs-controller"; -import { UiInputs } from "./ui-inputs"; -import { NewArenaEvent } from "./events/battle-scene"; -import { ArenaFlyout } from "./ui/arena-flyout"; +import { InputsController } from "#app/inputs-controller"; +import { UiInputs } from "#app/ui-inputs"; +import { NewArenaEvent } from "#app/events/battle-scene"; +import { ArenaFlyout } from "#app/ui/arena-flyout"; import { EaseType } from "#enums/ease-type"; import { BattleSpec } from "#enums/battle-spec"; import { BattleStyle } from "#enums/battle-style"; @@ -66,27 +66,27 @@ import { TimedEventManager } from "#app/timed-event-manager"; import { PokemonAnimType } from "#enums/pokemon-anim-type"; import i18next from "i18next"; import { TrainerType } from "#enums/trainer-type"; -import { battleSpecDialogue } from "./data/dialogue"; -import { LoadingScene } from "./loading-scene"; -import { LevelCapPhase } from "./phases/level-cap-phase"; -import { LoginPhase } from "./phases/login-phase"; -import { MessagePhase } from "./phases/message-phase"; -import { MovePhase } from "./phases/move-phase"; -import { NewBiomeEncounterPhase } from "./phases/new-biome-encounter-phase"; -import { NextEncounterPhase } from "./phases/next-encounter-phase"; -import { PokemonAnimPhase } from "./phases/pokemon-anim-phase"; -import { QuietFormChangePhase } from "./phases/quiet-form-change-phase"; -import { ReturnPhase } from "./phases/return-phase"; -import { SelectBiomePhase } from "./phases/select-biome-phase"; -import { ShowTrainerPhase } from "./phases/show-trainer-phase"; -import { SummonPhase } from "./phases/summon-phase"; -import { SwitchPhase } from "./phases/switch-phase"; -import { TitlePhase } from "./phases/title-phase"; -import { ToggleDoublePositionPhase } from "./phases/toggle-double-position-phase"; -import { TurnInitPhase } from "./phases/turn-init-phase"; -import { ShopCursorTarget } from "./enums/shop-cursor-target"; -import MysteryEncounter from "./data/mystery-encounters/mystery-encounter"; -import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "./data/mystery-encounters/mystery-encounters"; +import { battleSpecDialogue } from "#app/data/dialogue"; +import { LoadingScene } from "#app/loading-scene"; +import { LevelCapPhase } from "#app/phases/level-cap-phase"; +import { LoginPhase } from "#app/phases/login-phase"; +import { MessagePhase } from "#app/phases/message-phase"; +import { MovePhase } from "#app/phases/move-phase"; +import { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase"; +import { NextEncounterPhase } from "#app/phases/next-encounter-phase"; +import { PokemonAnimPhase } from "#app/phases/pokemon-anim-phase"; +import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; +import { ReturnPhase } from "#app/phases/return-phase"; +import { SelectBiomePhase } from "#app/phases/select-biome-phase"; +import { ShowTrainerPhase } from "#app/phases/show-trainer-phase"; +import { SummonPhase } from "#app/phases/summon-phase"; +import { SwitchPhase } from "#app/phases/switch-phase"; +import { TitlePhase } from "#app/phases/title-phase"; +import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase"; +import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import { ShopCursorTarget } from "#app/enums/shop-cursor-target"; +import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; +import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters"; import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; @@ -94,7 +94,8 @@ import HeldModifierConfig from "#app/interfaces/held-modifier-config"; import { ExpPhase } from "#app/phases/exp-phase"; import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; -import { ExpGainsSpeed } from "./enums/exp-gains-speed"; +import { ExpGainsSpeed } from "#enums/exp-gains-speed"; +import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; @@ -789,7 +790,7 @@ export default class BattleScene extends SceneBase { } getEnemyParty(): EnemyPokemon[] { - return this.currentBattle?.enemyParty || []; + return this.currentBattle?.enemyParty ?? []; } getEnemyPokemon(): EnemyPokemon | undefined { @@ -889,6 +890,9 @@ export default class BattleScene extends SceneBase { } const pokemon = new EnemyPokemon(this, species, level, trainerSlot, boss, dataSource); + if (Overrides.OPP_FUSION_OVERRIDE) { + pokemon.generateFusionSpecies(); + } overrideModifiers(this, false); overrideHeldItems(this, pokemon, false); @@ -1261,7 +1265,7 @@ export default class BattleScene extends SceneBase { const isEndlessFifthWave = this.gameMode.hasShortBiomes && (lastBattle.waveIndex % 5) === 0; const isWaveIndexMultipleOfFiftyMinusOne = (lastBattle.waveIndex % 50) === 49; const isNewBiome = isWaveIndexMultipleOfTen || isEndlessFifthWave || (isEndlessOrDaily && isWaveIndexMultipleOfFiftyMinusOne); - const resetArenaState = isNewBiome || [BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(this.currentBattle.battleType) || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS; + const resetArenaState = isNewBiome || [ BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER ].includes(this.currentBattle.battleType) || this.currentBattle.battleSpec === BattleSpec.FINAL_BOSS; this.getEnemyParty().forEach(enemyPokemon => enemyPokemon.destroy()); this.trySpreadPokerus(); if (!isNewBiome && (newWaveIndex % 10) === 5) { @@ -1355,69 +1359,69 @@ export default class BattleScene extends SceneBase { } switch (species.speciesId) { - case Species.UNOWN: - case Species.SHELLOS: - case Species.GASTRODON: - case Species.BASCULIN: - case Species.DEERLING: - case Species.SAWSBUCK: - case Species.FROAKIE: - case Species.FROGADIER: - case Species.SCATTERBUG: - case Species.SPEWPA: - case Species.VIVILLON: - case Species.FLABEBE: - case Species.FLOETTE: - case Species.FLORGES: - case Species.FURFROU: - case Species.PUMPKABOO: - case Species.GOURGEIST: - case Species.ORICORIO: - case Species.MAGEARNA: - case Species.ZARUDE: - case Species.SQUAWKABILLY: - case Species.TATSUGIRI: - case Species.PALDEA_TAUROS: - return Utils.randSeedInt(species.forms.length); - case Species.PIKACHU: - return Utils.randSeedInt(8); - case Species.EEVEE: - return Utils.randSeedInt(2); - case Species.GRENINJA: - return Utils.randSeedInt(2); - case Species.ZYGARDE: - return Utils.randSeedInt(3); - case Species.MINIOR: - return Utils.randSeedInt(6); - case Species.ALCREMIE: - return Utils.randSeedInt(9); - case Species.MEOWSTIC: - case Species.INDEEDEE: - case Species.BASCULEGION: - case Species.OINKOLOGNE: - return gender === Gender.FEMALE ? 1 : 0; - case Species.TOXTRICITY: - const lowkeyNatures = [ Nature.LONELY, Nature.BOLD, Nature.RELAXED, Nature.TIMID, Nature.SERIOUS, Nature.MODEST, Nature.MILD, Nature.QUIET, Nature.BASHFUL, Nature.CALM, Nature.GENTLE, Nature.CAREFUL ]; - if (nature !== undefined && lowkeyNatures.indexOf(nature) > -1) { - return 1; - } - return 0; - case Species.GIMMIGHOUL: - // Chest form can only be found in Mysterious Chest Encounter, if this is a game mode with MEs - if (this.gameMode.hasMysteryEncounters) { - return 1; // Wandering form - } else { + case Species.UNOWN: + case Species.SHELLOS: + case Species.GASTRODON: + case Species.BASCULIN: + case Species.DEERLING: + case Species.SAWSBUCK: + case Species.FROAKIE: + case Species.FROGADIER: + case Species.SCATTERBUG: + case Species.SPEWPA: + case Species.VIVILLON: + case Species.FLABEBE: + case Species.FLOETTE: + case Species.FLORGES: + case Species.FURFROU: + case Species.PUMPKABOO: + case Species.GOURGEIST: + case Species.ORICORIO: + case Species.MAGEARNA: + case Species.ZARUDE: + case Species.SQUAWKABILLY: + case Species.TATSUGIRI: + case Species.PALDEA_TAUROS: return Utils.randSeedInt(species.forms.length); - } + case Species.PIKACHU: + return Utils.randSeedInt(8); + case Species.EEVEE: + return Utils.randSeedInt(2); + case Species.GRENINJA: + return Utils.randSeedInt(2); + case Species.ZYGARDE: + return Utils.randSeedInt(4); + case Species.MINIOR: + return Utils.randSeedInt(6); + case Species.ALCREMIE: + return Utils.randSeedInt(9); + case Species.MEOWSTIC: + case Species.INDEEDEE: + case Species.BASCULEGION: + case Species.OINKOLOGNE: + return gender === Gender.FEMALE ? 1 : 0; + case Species.TOXTRICITY: + const lowkeyNatures = [ Nature.LONELY, Nature.BOLD, Nature.RELAXED, Nature.TIMID, Nature.SERIOUS, Nature.MODEST, Nature.MILD, Nature.QUIET, Nature.BASHFUL, Nature.CALM, Nature.GENTLE, Nature.CAREFUL ]; + if (nature !== undefined && lowkeyNatures.indexOf(nature) > -1) { + return 1; + } + return 0; + case Species.GIMMIGHOUL: + // Chest form can only be found in Mysterious Chest Encounter, if this is a game mode with MEs + if (this.gameMode.hasMysteryEncounters) { + return 1; // Wandering form + } else { + return Utils.randSeedInt(species.forms.length); + } } if (ignoreArena) { switch (species.speciesId) { - case Species.BURMY: - case Species.WORMADAM: - case Species.ROTOM: - case Species.LYCANROC: - return Utils.randSeedInt(species.forms.length); + case Species.BURMY: + case Species.WORMADAM: + case Species.ROTOM: + case Species.LYCANROC: + return Utils.randSeedInt(species.forms.length); } return 0; } @@ -1758,14 +1762,14 @@ export default class BattleScene extends SceneBase { if (fromArenaPool) { return this.arena.randomSpecies(waveIndex, level, undefined, getPartyLuckValue(this.party)); } - const filteredSpecies = speciesFilter ? [...new Set(allSpecies.filter(s => s.isCatchable()).filter(speciesFilter).map(s => { + const filteredSpecies = speciesFilter ? [ ...new Set(allSpecies.filter(s => s.isCatchable()).filter(speciesFilter).map(s => { if (!filterAllEvolutions) { while (pokemonPrevolutions.hasOwnProperty(s.speciesId)) { s = getPokemonSpecies(pokemonPrevolutions[s.speciesId]); } } return s; - }))] : allSpecies.filter(s => s.isCatchable()); + })) ] : allSpecies.filter(s => s.isCatchable()); return filteredSpecies[Utils.randSeedInt(filteredSpecies.length)]; } @@ -1882,17 +1886,17 @@ export default class BattleScene extends SceneBase { const soundDetails = sound.key.split("/"); switch (soundDetails[0]) { - case "battle_anims": - case "cry": - if (soundDetails[1].startsWith("PRSFX- ")) { - sound.setVolume(this.masterVolume*this.fieldVolume*0.5); - } else { - sound.setVolume(this.masterVolume*this.fieldVolume); - } - break; - case "se": - case "ui": - sound.setVolume(this.masterVolume*this.seVolume); + case "battle_anims": + case "cry": + if (soundDetails[1].startsWith("PRSFX- ")) { + sound.setVolume(this.masterVolume * this.fieldVolume * 0.5); + } else { + sound.setVolume(this.masterVolume * this.fieldVolume); + } + break; + case "se": + case "ui": + sound.setVolume(this.masterVolume * this.seVolume); } } } @@ -1932,31 +1936,31 @@ export default class BattleScene extends SceneBase { const keyDetails = key.split("/"); config["volume"] = config["volume"] ?? 1; switch (keyDetails[0]) { - case "level_up_fanfare": - case "item_fanfare": - case "minor_fanfare": - case "heal": - case "evolution": - case "evolution_fanfare": + case "level_up_fanfare": + case "item_fanfare": + case "minor_fanfare": + case "heal": + case "evolution": + case "evolution_fanfare": // These sounds are loaded in as BGM, but played as sound effects // When these sounds are updated in updateVolume(), they are treated as BGM however because they are placed in the BGM Cache through being called by playSoundWithoutBGM() - config["volume"] *= (this.masterVolume * this.bgmVolume); - break; - case "battle_anims": - case "cry": - config["volume"] *= (this.masterVolume * this.fieldVolume); - //PRSFX sound files are unusually loud - if (keyDetails[1].startsWith("PRSFX- ")) { - config["volume"] *= 0.5; - } - break; - case "ui": + config["volume"] *= (this.masterVolume * this.bgmVolume); + break; + case "battle_anims": + case "cry": + config["volume"] *= (this.masterVolume * this.fieldVolume); + //PRSFX sound files are unusually loud + if (keyDetails[1].startsWith("PRSFX- ")) { + config["volume"] *= 0.5; + } + break; + case "ui": //As of, right now this applies to the "select", "menu_open", "error" sound effects - config["volume"] *= (this.masterVolume * this.uiVolume); - break; - case "se": - config["volume"] *= (this.masterVolume * this.seVolume); - break; + config["volume"] *= (this.masterVolume * this.uiVolume); + break; + case "se": + config["volume"] *= (this.masterVolume * this.seVolume); + break; } this.sound.play(key, config); return this.sound.get(key) as AnySound; @@ -1985,208 +1989,208 @@ export default class BattleScene extends SceneBase { getBgmLoopPoint(bgmName: string): number { switch (bgmName) { - case "battle_kanto_champion": //B2W2 Kanto Champion Battle - return 13.950; - case "battle_johto_champion": //B2W2 Johto Champion Battle - return 23.498; - case "battle_hoenn_champion_g5": //B2W2 Hoenn Champion Battle - return 11.328; - case "battle_hoenn_champion_g6": //ORAS Hoenn Champion Battle - return 11.762; - case "battle_sinnoh_champion": //B2W2 Sinnoh Champion Battle - return 12.235; - case "battle_champion_alder": //BW Unova Champion Battle - return 27.653; - case "battle_champion_iris": //B2W2 Unova Champion Battle - return 10.145; - case "battle_kalos_champion": //XY Kalos Champion Battle - return 10.380; - case "battle_alola_champion": //USUM Alola Champion Battle - return 13.025; - case "battle_galar_champion": //SWSH Galar Champion Battle - return 61.635; - case "battle_champion_geeta": //SV Champion Geeta Battle - return 37.447; - case "battle_champion_nemona": //SV Champion Nemona Battle - return 14.914; - case "battle_champion_kieran": //SV Champion Kieran Battle - return 7.206; - case "battle_hoenn_elite": //ORAS Elite Four Battle - return 11.350; - case "battle_unova_elite": //BW Elite Four Battle - return 17.730; - case "battle_kalos_elite": //XY Elite Four Battle - return 12.340; - case "battle_alola_elite": //SM Elite Four Battle - return 19.212; - case "battle_galar_elite": //SWSH League Tournament Battle - return 164.069; - case "battle_paldea_elite": //SV Elite Four Battle - return 12.770; - case "battle_bb_elite": //SV BB League Elite Four Battle - return 19.434; - case "battle_final_encounter": //PMD RTDX Rayquaza's Domain - return 19.159; - case "battle_final": //BW Ghetsis Battle - return 16.453; - case "battle_kanto_gym": //B2W2 Kanto Gym Battle - return 13.857; - case "battle_johto_gym": //B2W2 Johto Gym Battle - return 12.911; - case "battle_hoenn_gym": //B2W2 Hoenn Gym Battle - return 12.379; - case "battle_sinnoh_gym": //B2W2 Sinnoh Gym Battle - return 13.122; - case "battle_unova_gym": //BW Unova Gym Battle - return 19.145; - case "battle_kalos_gym": //XY Kalos Gym Battle - return 44.810; - case "battle_galar_gym": //SWSH Galar Gym Battle - return 171.262; - case "battle_paldea_gym": //SV Paldea Gym Battle - return 127.489; - case "battle_legendary_kanto": //XY Kanto Legendary Battle - return 32.966; - case "battle_legendary_raikou": //HGSS Raikou Battle - return 12.632; - case "battle_legendary_entei": //HGSS Entei Battle - return 2.905; - case "battle_legendary_suicune": //HGSS Suicune Battle - return 12.636; - case "battle_legendary_lugia": //HGSS Lugia Battle - return 19.770; - case "battle_legendary_ho_oh": //HGSS Ho-oh Battle - return 17.668; - case "battle_legendary_regis_g5": //B2W2 Legendary Titan Battle - return 49.500; - case "battle_legendary_regis_g6": //ORAS Legendary Titan Battle - return 21.130; - case "battle_legendary_gro_kyo": //ORAS Groudon & Kyogre Battle - return 10.547; - case "battle_legendary_rayquaza": //ORAS Rayquaza Battle - return 10.495; - case "battle_legendary_deoxys": //ORAS Deoxys Battle - return 13.333; - case "battle_legendary_lake_trio": //ORAS Lake Guardians Battle - return 16.887; - case "battle_legendary_sinnoh": //ORAS Sinnoh Legendary Battle - return 22.770; - case "battle_legendary_dia_pal": //ORAS Dialga & Palkia Battle - return 16.009; - case "battle_legendary_origin_forme": //LA Origin Dialga & Palkia Battle - return 18.961; - case "battle_legendary_giratina": //ORAS Giratina Battle - return 10.451; - case "battle_legendary_arceus": //HGSS Arceus Battle - return 9.595; - case "battle_legendary_unova": //BW Unova Legendary Battle - return 13.855; - case "battle_legendary_kyurem": //BW Kyurem Battle - return 18.314; - case "battle_legendary_res_zek": //BW Reshiram & Zekrom Battle - return 18.329; - case "battle_legendary_xern_yvel": //XY Xerneas & Yveltal Battle - return 26.468; - case "battle_legendary_tapu": //SM Tapu Battle - return 0.000; - case "battle_legendary_sol_lun": //SM Solgaleo & Lunala Battle - return 6.525; - case "battle_legendary_ub": //SM Ultra Beast Battle - return 9.818; - case "battle_legendary_dusk_dawn": //USUM Dusk Mane & Dawn Wings Necrozma Battle - return 5.211; - case "battle_legendary_ultra_nec": //USUM Ultra Necrozma Battle - return 10.344; - case "battle_legendary_zac_zam": //SWSH Zacian & Zamazenta Battle - return 11.424; - case "battle_legendary_glas_spec": //SWSH Glastrier & Spectrier Battle - return 12.503; - case "battle_legendary_calyrex": //SWSH Calyrex Battle - return 50.641; - case "battle_legendary_riders": //SWSH Ice & Shadow Rider Calyrex Battle - return 18.155; - case "battle_legendary_birds_galar": //SWSH Galarian Legendary Birds Battle - return 0.175; - case "battle_legendary_ruinous": //SV Treasures of Ruin Battle - return 6.333; - case "battle_legendary_kor_mir": //SV Depths of Area Zero Battle - return 6.442; - case "battle_legendary_loyal_three": //SV Loyal Three Battle - return 6.500; - case "battle_legendary_ogerpon": //SV Ogerpon Battle - return 14.335; - case "battle_legendary_terapagos": //SV Terapagos Battle - return 24.377; - case "battle_legendary_pecharunt": //SV Pecharunt Battle - return 6.508; - case "battle_rival": //BW Rival Battle - return 14.110; - case "battle_rival_2": //BW N Battle - return 17.714; - case "battle_rival_3": //BW Final N Battle - return 17.586; - case "battle_trainer": //BW Trainer Battle - return 13.686; - case "battle_wild": //BW Wild Battle - return 12.703; - case "battle_wild_strong": //BW Strong Wild Battle - return 13.940; - case "end_summit": //PMD RTDX Sky Tower Summit - return 30.025; - case "battle_rocket_grunt": //HGSS Team Rocket Battle - return 12.707; - case "battle_aqua_magma_grunt": //ORAS Team Aqua & Magma Battle - return 12.062; - case "battle_galactic_grunt": //BDSP Team Galactic Battle - return 13.043; - case "battle_plasma_grunt": //BW Team Plasma Battle - return 12.974; - case "battle_flare_grunt": //XY Team Flare Battle - return 4.228; - case "battle_aether_grunt": // SM Aether Foundation Battle - return 16.00; - case "battle_skull_grunt": // SM Team Skull Battle - return 20.87; - case "battle_macro_grunt": // SWSH Trainer Battle - return 11.56; - case "battle_star_grunt": //SV Team Star Battle - return 133.362; - case "battle_galactic_admin": //BDSP Team Galactic Admin Battle - return 11.997; - case "battle_skull_admin": //SM Team Skull Admin Battle - return 15.463; - case "battle_oleana": //SWSH Oleana Battle - return 14.110; - case "battle_star_admin": //SV Team Star Boss Battle - return 9.493; - case "battle_rocket_boss": //USUM Giovanni Battle - return 9.115; - case "battle_aqua_magma_boss": //ORAS Archie & Maxie Battle - return 14.847; - case "battle_galactic_boss": //BDSP Cyrus Battle - return 106.962; - case "battle_plasma_boss": //B2W2 Ghetsis Battle - return 25.624; - case "battle_flare_boss": //XY Lysandre Battle - return 8.085; - case "battle_aether_boss": //SM Lusamine Battle - return 11.33; - case "battle_skull_boss": //SM Guzma Battle - return 13.13; - case "battle_macro_boss": //SWSH Rose Battle - return 11.42; - case "battle_star_boss": //SV Cassiopeia Battle - return 25.764; - case "mystery_encounter_gen_5_gts": // BW GTS - return 8.52; - case "mystery_encounter_gen_6_gts": // XY GTS - return 9.24; - case "mystery_encounter_fun_and_games": // EoS Guildmaster Wigglytuff - return 4.78; - case "mystery_encounter_weird_dream": // EoS Temporal Spire - return 41.42; - case "mystery_encounter_delibirdy": // Firel Delibirdy - return 82.28; + case "battle_kanto_champion": //B2W2 Kanto Champion Battle + return 13.950; + case "battle_johto_champion": //B2W2 Johto Champion Battle + return 23.498; + case "battle_hoenn_champion_g5": //B2W2 Hoenn Champion Battle + return 11.328; + case "battle_hoenn_champion_g6": //ORAS Hoenn Champion Battle + return 11.762; + case "battle_sinnoh_champion": //B2W2 Sinnoh Champion Battle + return 12.235; + case "battle_champion_alder": //BW Unova Champion Battle + return 27.653; + case "battle_champion_iris": //B2W2 Unova Champion Battle + return 10.145; + case "battle_kalos_champion": //XY Kalos Champion Battle + return 10.380; + case "battle_alola_champion": //USUM Alola Champion Battle + return 13.025; + case "battle_galar_champion": //SWSH Galar Champion Battle + return 61.635; + case "battle_champion_geeta": //SV Champion Geeta Battle + return 37.447; + case "battle_champion_nemona": //SV Champion Nemona Battle + return 14.914; + case "battle_champion_kieran": //SV Champion Kieran Battle + return 7.206; + case "battle_hoenn_elite": //ORAS Elite Four Battle + return 11.350; + case "battle_unova_elite": //BW Elite Four Battle + return 17.730; + case "battle_kalos_elite": //XY Elite Four Battle + return 12.340; + case "battle_alola_elite": //SM Elite Four Battle + return 19.212; + case "battle_galar_elite": //SWSH League Tournament Battle + return 164.069; + case "battle_paldea_elite": //SV Elite Four Battle + return 12.770; + case "battle_bb_elite": //SV BB League Elite Four Battle + return 19.434; + case "battle_final_encounter": //PMD RTDX Rayquaza's Domain + return 19.159; + case "battle_final": //BW Ghetsis Battle + return 16.453; + case "battle_kanto_gym": //B2W2 Kanto Gym Battle + return 13.857; + case "battle_johto_gym": //B2W2 Johto Gym Battle + return 12.911; + case "battle_hoenn_gym": //B2W2 Hoenn Gym Battle + return 12.379; + case "battle_sinnoh_gym": //B2W2 Sinnoh Gym Battle + return 13.122; + case "battle_unova_gym": //BW Unova Gym Battle + return 19.145; + case "battle_kalos_gym": //XY Kalos Gym Battle + return 44.810; + case "battle_galar_gym": //SWSH Galar Gym Battle + return 171.262; + case "battle_paldea_gym": //SV Paldea Gym Battle + return 127.489; + case "battle_legendary_kanto": //XY Kanto Legendary Battle + return 32.966; + case "battle_legendary_raikou": //HGSS Raikou Battle + return 12.632; + case "battle_legendary_entei": //HGSS Entei Battle + return 2.905; + case "battle_legendary_suicune": //HGSS Suicune Battle + return 12.636; + case "battle_legendary_lugia": //HGSS Lugia Battle + return 19.770; + case "battle_legendary_ho_oh": //HGSS Ho-oh Battle + return 17.668; + case "battle_legendary_regis_g5": //B2W2 Legendary Titan Battle + return 49.500; + case "battle_legendary_regis_g6": //ORAS Legendary Titan Battle + return 21.130; + case "battle_legendary_gro_kyo": //ORAS Groudon & Kyogre Battle + return 10.547; + case "battle_legendary_rayquaza": //ORAS Rayquaza Battle + return 10.495; + case "battle_legendary_deoxys": //ORAS Deoxys Battle + return 13.333; + case "battle_legendary_lake_trio": //ORAS Lake Guardians Battle + return 16.887; + case "battle_legendary_sinnoh": //ORAS Sinnoh Legendary Battle + return 22.770; + case "battle_legendary_dia_pal": //ORAS Dialga & Palkia Battle + return 16.009; + case "battle_legendary_origin_forme": //LA Origin Dialga & Palkia Battle + return 18.961; + case "battle_legendary_giratina": //ORAS Giratina Battle + return 10.451; + case "battle_legendary_arceus": //HGSS Arceus Battle + return 9.595; + case "battle_legendary_unova": //BW Unova Legendary Battle + return 13.855; + case "battle_legendary_kyurem": //BW Kyurem Battle + return 18.314; + case "battle_legendary_res_zek": //BW Reshiram & Zekrom Battle + return 18.329; + case "battle_legendary_xern_yvel": //XY Xerneas & Yveltal Battle + return 26.468; + case "battle_legendary_tapu": //SM Tapu Battle + return 0.000; + case "battle_legendary_sol_lun": //SM Solgaleo & Lunala Battle + return 6.525; + case "battle_legendary_ub": //SM Ultra Beast Battle + return 9.818; + case "battle_legendary_dusk_dawn": //USUM Dusk Mane & Dawn Wings Necrozma Battle + return 5.211; + case "battle_legendary_ultra_nec": //USUM Ultra Necrozma Battle + return 10.344; + case "battle_legendary_zac_zam": //SWSH Zacian & Zamazenta Battle + return 11.424; + case "battle_legendary_glas_spec": //SWSH Glastrier & Spectrier Battle + return 12.503; + case "battle_legendary_calyrex": //SWSH Calyrex Battle + return 50.641; + case "battle_legendary_riders": //SWSH Ice & Shadow Rider Calyrex Battle + return 18.155; + case "battle_legendary_birds_galar": //SWSH Galarian Legendary Birds Battle + return 0.175; + case "battle_legendary_ruinous": //SV Treasures of Ruin Battle + return 6.333; + case "battle_legendary_kor_mir": //SV Depths of Area Zero Battle + return 6.442; + case "battle_legendary_loyal_three": //SV Loyal Three Battle + return 6.500; + case "battle_legendary_ogerpon": //SV Ogerpon Battle + return 14.335; + case "battle_legendary_terapagos": //SV Terapagos Battle + return 24.377; + case "battle_legendary_pecharunt": //SV Pecharunt Battle + return 6.508; + case "battle_rival": //BW Rival Battle + return 14.110; + case "battle_rival_2": //BW N Battle + return 17.714; + case "battle_rival_3": //BW Final N Battle + return 17.586; + case "battle_trainer": //BW Trainer Battle + return 13.686; + case "battle_wild": //BW Wild Battle + return 12.703; + case "battle_wild_strong": //BW Strong Wild Battle + return 13.940; + case "end_summit": //PMD RTDX Sky Tower Summit + return 30.025; + case "battle_rocket_grunt": //HGSS Team Rocket Battle + return 12.707; + case "battle_aqua_magma_grunt": //ORAS Team Aqua & Magma Battle + return 12.062; + case "battle_galactic_grunt": //BDSP Team Galactic Battle + return 13.043; + case "battle_plasma_grunt": //BW Team Plasma Battle + return 12.974; + case "battle_flare_grunt": //XY Team Flare Battle + return 4.228; + case "battle_aether_grunt": // SM Aether Foundation Battle + return 16.00; + case "battle_skull_grunt": // SM Team Skull Battle + return 20.87; + case "battle_macro_grunt": // SWSH Trainer Battle + return 11.56; + case "battle_star_grunt": //SV Team Star Battle + return 133.362; + case "battle_galactic_admin": //BDSP Team Galactic Admin Battle + return 11.997; + case "battle_skull_admin": //SM Team Skull Admin Battle + return 15.463; + case "battle_oleana": //SWSH Oleana Battle + return 14.110; + case "battle_star_admin": //SV Team Star Boss Battle + return 9.493; + case "battle_rocket_boss": //USUM Giovanni Battle + return 9.115; + case "battle_aqua_magma_boss": //ORAS Archie & Maxie Battle + return 14.847; + case "battle_galactic_boss": //BDSP Cyrus Battle + return 106.962; + case "battle_plasma_boss": //B2W2 Ghetsis Battle + return 25.624; + case "battle_flare_boss": //XY Lysandre Battle + return 8.085; + case "battle_aether_boss": //SM Lusamine Battle + return 11.33; + case "battle_skull_boss": //SM Guzma Battle + return 13.13; + case "battle_macro_boss": //SWSH Rose Battle + return 11.42; + case "battle_star_boss": //SV Cassiopeia Battle + return 25.764; + case "mystery_encounter_gen_5_gts": // BW GTS + return 8.52; + case "mystery_encounter_gen_6_gts": // XY GTS + return 9.24; + case "mystery_encounter_fun_and_games": // EoS Guildmaster Wigglytuff + return 4.78; + case "mystery_encounter_weird_dream": // EoS Temporal Spire + return 41.42; + case "mystery_encounter_delibirdy": // Firel Delibirdy + return 82.28; } return 0; @@ -2221,7 +2225,7 @@ export default class BattleScene extends SceneBase { * */ pushConditionalPhase(phase: Phase, condition: () => boolean): void { - this.conditionalQueue.push([condition, phase]); + this.conditionalQueue.push([ condition, phase ]); } /** @@ -2313,7 +2317,10 @@ export default class BattleScene extends SceneBase { } } - this.currentPhase?.start(); + if (this.currentPhase) { + console.log(`%cStart Phase ${this.currentPhase.constructor.name}`, "color:green;"); + this.currentPhase.start(); + } } overridePhase(phase: Phase): boolean { @@ -2323,6 +2330,7 @@ export default class BattleScene extends SceneBase { this.standbyPhase = this.currentPhase; this.currentPhase = phase; + console.log(`%cStart Phase ${phase.constructor.name}`, "color:green;"); phase.start(); return true; @@ -2356,17 +2364,6 @@ export default class BattleScene extends SceneBase { return false; } - pushMovePhase(movePhase: MovePhase, priorityOverride?: integer): void { - const movePriority = new Utils.IntegerHolder(priorityOverride !== undefined ? priorityOverride : movePhase.move.getMove().priority); - applyAbAttrs(ChangeMovePriorityAbAttr, movePhase.pokemon, null, false, movePhase.move.getMove(), movePriority); - const lowerPriorityPhase = this.phaseQueue.find(p => p instanceof MovePhase && p.move.getMove().priority < movePriority.value); - if (lowerPriorityPhase) { - this.phaseQueue.splice(this.phaseQueue.indexOf(lowerPriorityPhase), 0, movePhase); - } else { - this.pushPhase(movePhase); - } - } - /** * Tries to add the input phase to index before target phase in the phaseQueue, else simply calls unshiftPhase() * @param phase {@linkcode Phase} the phase to be added @@ -2429,7 +2426,7 @@ export default class BattleScene extends SceneBase { return Math.floor(moneyValue / 10) * 10; } - addModifier(modifier: Modifier | null, ignoreUpdate?: boolean, playSound?: boolean, virtual?: boolean, instant?: boolean): Promise { + addModifier(modifier: Modifier | null, ignoreUpdate?: boolean, playSound?: boolean, virtual?: boolean, instant?: boolean, cost?: number): Promise { if (!modifier) { return Promise.resolve(false); } @@ -2486,6 +2483,8 @@ export default class BattleScene extends SceneBase { } } else if (modifier instanceof FusePokemonModifier) { args.push(this.getPokemonById(modifier.fusePokemonId) as PlayerPokemon); + } else if (modifier instanceof RememberMoveModifier && !Utils.isNullOrUndefined(cost)) { + args.push(cost); } if (modifier.shouldApply(pokemon, ...args)) { @@ -2498,7 +2497,7 @@ export default class BattleScene extends SceneBase { } } - return Promise.allSettled([this.party.map(p => p.updateInfo(instant)), ...modifierPromises]).then(() => resolve(success)); + return Promise.allSettled([ this.party.map(p => p.updateInfo(instant)), ...modifierPromises ]).then(() => resolve(success)); } else { const args = [ this ]; if (modifier.shouldApply(...args)) { @@ -2684,7 +2683,7 @@ export default class BattleScene extends SceneBase { } /** - * Removes all modifiers from enemy of PersistentModifier type + * Removes all modifiers from enemy pokemon of {@linkcode PersistentModifier} type */ clearEnemyModifiers(): void { const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PersistentModifier); @@ -2695,10 +2694,11 @@ export default class BattleScene extends SceneBase { } /** - * Removes all modifiers from enemy of PokemonHeldItemModifier type + * Removes all modifiers from enemy pokemon of {@linkcode PokemonHeldItemModifier} type + * @param pokemon - If specified, only removes held items from that {@linkcode Pokemon} */ - clearEnemyHeldItemModifiers(): void { - const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PokemonHeldItemModifier); + clearEnemyHeldItemModifiers(pokemon?: Pokemon): void { + const modifiersToRemove = this.enemyModifiers.filter(m => m instanceof PokemonHeldItemModifier && (!pokemon || m.getPokemon(this) === pokemon)); for (const m of modifiersToRemove) { this.enemyModifiers.splice(this.enemyModifiers.indexOf(m), 1); } @@ -2818,7 +2818,7 @@ export default class BattleScene extends SceneBase { return mods; } const rand = Utils.randSeedInt(mods.length); - return [mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand))]; + return [ mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand)) ]; }; modifiers = shuffleModifiers(modifiers); }, scene.currentBattle.turn << 4, scene.waveSeed); @@ -2978,7 +2978,7 @@ export default class BattleScene extends SceneBase { keys.push(p.getBattleSpriteKey(true, true)); keys.push("cry/" + p.species.getCryKey(p.formIndex)); if (p.fusionSpecies) { - keys.push("cry/"+p.fusionSpecies.getCryKey(p.fusionFormIndex)); + keys.push("cry/" + p.fusionSpecies.getCryKey(p.fusionFormIndex)); } }); // enemyParty has to be operated on separately from playerParty because playerPokemon =/= enemyPokemon @@ -2987,7 +2987,7 @@ export default class BattleScene extends SceneBase { keys.push(p.getSpriteKey(true)); keys.push("cry/" + p.species.getCryKey(p.formIndex)); if (p.fusionSpecies) { - keys.push("cry/"+p.fusionSpecies.getCryKey(p.fusionFormIndex)); + keys.push("cry/" + p.fusionSpecies.getCryKey(p.fusionFormIndex)); } }); return keys; @@ -3055,7 +3055,7 @@ export default class BattleScene extends SceneBase { const pId = partyMember.id; const participated = participantIds.has(pId); if (participated && pokemonDefeated) { - partyMember.addFriendship(2); + partyMember.addFriendship(FRIENDSHIP_GAIN_FROM_BATTLE); const machoBraceModifier = partyMember.getHeldItems().find(m => m instanceof PokemonIncrementingStatModifier); if (machoBraceModifier && machoBraceModifier.stackCount < machoBraceModifier.getMaxStackCount(this)) { machoBraceModifier.stackCount++; @@ -3135,7 +3135,7 @@ export default class BattleScene extends SceneBase { * @param sessionDataEncounterType */ private isWaveMysteryEncounter(newBattleType: BattleType, waveIndex: number, sessionDataEncounterType?: MysteryEncounterType): boolean { - const [lowestMysteryEncounterWave, highestMysteryEncounterWave] = this.gameMode.getMysteryEncounterLegalWaves(); + const [ lowestMysteryEncounterWave, highestMysteryEncounterWave ] = this.gameMode.getMysteryEncounterLegalWaves(); if (this.gameMode.hasMysteryEncounters && newBattleType === BattleType.WILD && !this.gameMode.isBoss(waveIndex) && waveIndex < highestMysteryEncounterWave && waveIndex > lowestMysteryEncounterWave) { // Base spawn weight is BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT/256, and increases by WEIGHT_INCREMENT_ON_SPAWN_MISS/256 for each missed attempt at spawning an encounter on a valid floor const sessionEncounterRate = this.mysteryEncounterSaveData.encounterSpawnChance; @@ -3169,13 +3169,20 @@ export default class BattleScene extends SceneBase { /** * Loads or generates a mystery encounter * @param encounterType used to load session encounter when restarting game, etc. + * @param canBypass optional boolean to indicate that the request is coming from a function that needs to access a Mystery Encounter outside of gameplay requirements * @returns */ - getMysteryEncounter(encounterType?: MysteryEncounterType): MysteryEncounter { + getMysteryEncounter(encounterType?: MysteryEncounterType, canBypass?: boolean): MysteryEncounter { // Loading override or session encounter let encounter: MysteryEncounter | null; if (!isNullOrUndefined(Overrides.MYSTERY_ENCOUNTER_OVERRIDE) && allMysteryEncounters.hasOwnProperty(Overrides.MYSTERY_ENCOUNTER_OVERRIDE)) { encounter = allMysteryEncounters[Overrides.MYSTERY_ENCOUNTER_OVERRIDE]; + if (canBypass) { + return encounter; + } + } else if (canBypass) { + encounter = allMysteryEncounters[encounterType ?? -1]; + return encounter; } else { encounter = !isNullOrUndefined(encounterType) ? allMysteryEncounters[encounterType] : null; } @@ -3201,7 +3208,7 @@ export default class BattleScene extends SceneBase { } // See Enum values for base tier weights - const tierWeights = [MysteryEncounterTier.COMMON, MysteryEncounterTier.GREAT, MysteryEncounterTier.ULTRA, MysteryEncounterTier.ROGUE]; + const tierWeights = [ MysteryEncounterTier.COMMON, MysteryEncounterTier.GREAT, MysteryEncounterTier.ULTRA, MysteryEncounterTier.ROGUE ]; // Adjust tier weights by previously encountered events to lower odds of only Common/Great in run this.mysteryEncounterSaveData.encounteredEvents.forEach(seenEncounterData => { diff --git a/src/battle.ts b/src/battle.ts index 412fd1b5184..6086c2ceb4e 100644 --- a/src/battle.ts +++ b/src/battle.ts @@ -497,7 +497,7 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], rand } /* 1/3 chance for evil team grunts to be double battles */ - const evilTeamGrunts = [TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT]; + const evilTeamGrunts = [ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ]; const isEvilTeamGrunt = evilTeamGrunts.includes(trainerTypes[rand]); if (trainerConfigs[trainerTypes[rand]].hasDouble && isEvilTeamGrunt) { @@ -527,34 +527,34 @@ export const classicFixedBattles: FixedBattleConfigs = { .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), [25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_2, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) - .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }), + .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }), [35]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), [55]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_3, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) - .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }), + .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }), [62]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), [64]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), [66]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) - .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ] ], true)), + .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true)), [95]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_4, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) - .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }), + .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }), [112]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_GRUNT, TrainerType.MAGMA_GRUNT, TrainerType.AQUA_GRUNT, TrainerType.GALACTIC_GRUNT, TrainerType.PLASMA_GRUNT, TrainerType.FLARE_GRUNT, TrainerType.AETHER_GRUNT, TrainerType.SKULL_GRUNT, TrainerType.MACRO_GRUNT, TrainerType.STAR_GRUNT ], true)), [114]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) - .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ] ], true, 1)), + .setGetTrainerFunc(getRandomTrainerFunc([[ TrainerType.ARCHER, TrainerType.ARIANA, TrainerType.PROTON, TrainerType.PETREL ], [ TrainerType.TABITHA, TrainerType.COURTNEY ], [ TrainerType.MATT, TrainerType.SHELLY ], [ TrainerType.JUPITER, TrainerType.MARS, TrainerType.SATURN ], [ TrainerType.ZINZOLIN, TrainerType.ROOD ], [ TrainerType.XEROSIC, TrainerType.BRYONY ], TrainerType.FABA, TrainerType.PLUMERIA, TrainerType.OLEANA, [ TrainerType.GIACOMO, TrainerType.MELA, TrainerType.ATTICUS, TrainerType.ORTEGA, TrainerType.ERI ]], true, 1)), [ClassicFixedBossWaves.EVIL_BOSS_1]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_1, TrainerType.MAXIE, TrainerType.ARCHIE, TrainerType.CYRUS, TrainerType.GHETSIS, TrainerType.LYSANDRE, TrainerType.LUSAMINE, TrainerType.GUZMA, TrainerType.ROSE, TrainerType.PENNY ])) - .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }), + .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }), [145]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_5, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) - .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }), + .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }), [ClassicFixedBossWaves.EVIL_BOSS_2]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(35) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.ROCKET_BOSS_GIOVANNI_2, TrainerType.MAXIE_2, TrainerType.ARCHIE_2, TrainerType.CYRUS_2, TrainerType.GHETSIS_2, TrainerType.LYSANDRE_2, TrainerType.LUSAMINE_2, TrainerType.GUZMA_2, TrainerType.ROSE_2, TrainerType.PENNY_2 ])) - .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA], allowLuckUpgrades: false }), + .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.ULTRA ], allowLuckUpgrades: false }), [182]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, [ TrainerType.HALA, TrainerType.MOLAYNE ], TrainerType.MARNIE_ELITE, TrainerType.RIKA, TrainerType.CRISPIN ])), [184]: new FixedBattleConfig().setBattleType(BattleType.TRAINER).setSeedOffsetWave(182) @@ -567,5 +567,5 @@ export const classicFixedBattles: FixedBattleConfigs = { .setGetTrainerFunc(getRandomTrainerFunc([ TrainerType.BLUE, [ TrainerType.RED, TrainerType.LANCE_CHAMPION ], [ TrainerType.STEVEN, TrainerType.WALLACE ], TrainerType.CYNTHIA, [ TrainerType.ALDER, TrainerType.IRIS ], TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, [ TrainerType.GEETA, TrainerType.NEMONA ], TrainerType.KIERAN ])), [195]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL_6, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)) - .setCustomModifierRewards({ guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], allowLuckUpgrades: false }) + .setCustomModifierRewards({ guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], allowLuckUpgrades: false }) }; diff --git a/src/configs/inputs/cfg_keyboard_qwerty.ts b/src/configs/inputs/cfg_keyboard_qwerty.ts index 09a02f02836..5ddc12e8784 100644 --- a/src/configs/inputs/cfg_keyboard_qwerty.ts +++ b/src/configs/inputs/cfg_keyboard_qwerty.ts @@ -1,5 +1,5 @@ -import {Button} from "#enums/buttons"; -import {SettingKeyboard} from "#app/system/settings/settings-keyboard"; +import { Button } from "#enums/buttons"; +import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; const cfg_keyboard_qwerty = { padID: "default", diff --git a/src/configs/inputs/configHandler.ts b/src/configs/inputs/configHandler.ts index 45fb033e9fa..50be692cbc3 100644 --- a/src/configs/inputs/configHandler.ts +++ b/src/configs/inputs/configHandler.ts @@ -1,4 +1,4 @@ -import {Device} from "#enums/devices"; +import { Device } from "#enums/devices"; /** * Retrieves the key associated with the specified keycode from the mapping. diff --git a/src/configs/inputs/pad_dualshock.ts b/src/configs/inputs/pad_dualshock.ts index 742040958b4..2fbdd0ddfaa 100644 --- a/src/configs/inputs/pad_dualshock.ts +++ b/src/configs/inputs/pad_dualshock.ts @@ -1,5 +1,5 @@ -import {SettingGamepad} from "../../system/settings/settings-gamepad"; -import {Button} from "#enums/buttons"; +import { SettingGamepad } from "../../system/settings/settings-gamepad"; +import { Button } from "#enums/buttons"; /** * Dualshock mapping diff --git a/src/configs/inputs/pad_generic.ts b/src/configs/inputs/pad_generic.ts index 88ff66e231c..256af8f0fe3 100644 --- a/src/configs/inputs/pad_generic.ts +++ b/src/configs/inputs/pad_generic.ts @@ -1,5 +1,5 @@ -import {SettingGamepad} from "../../system/settings/settings-gamepad"; -import {Button} from "#enums/buttons"; +import { SettingGamepad } from "../../system/settings/settings-gamepad"; +import { Button } from "#enums/buttons"; /** * Generic pad mapping diff --git a/src/configs/inputs/pad_procon.ts b/src/configs/inputs/pad_procon.ts index be751cc3acc..98d17c4ef57 100644 --- a/src/configs/inputs/pad_procon.ts +++ b/src/configs/inputs/pad_procon.ts @@ -1,5 +1,5 @@ -import {SettingGamepad} from "#app/system/settings/settings-gamepad"; -import {Button} from "#enums/buttons"; +import { SettingGamepad } from "#app/system/settings/settings-gamepad"; +import { Button } from "#enums/buttons"; /** * Nintendo Pro Controller mapping diff --git a/src/configs/inputs/pad_unlicensedSNES.ts b/src/configs/inputs/pad_unlicensedSNES.ts index 8a7f3e78f98..77e68e6a644 100644 --- a/src/configs/inputs/pad_unlicensedSNES.ts +++ b/src/configs/inputs/pad_unlicensedSNES.ts @@ -1,5 +1,5 @@ -import {SettingGamepad} from "../../system/settings/settings-gamepad"; -import {Button} from "#enums/buttons"; +import { SettingGamepad } from "../../system/settings/settings-gamepad"; +import { Button } from "#enums/buttons"; /** * 081f-e401 - UnlicensedSNES diff --git a/src/configs/inputs/pad_xbox360.ts b/src/configs/inputs/pad_xbox360.ts index e003ccc8e87..6afc452f50b 100644 --- a/src/configs/inputs/pad_xbox360.ts +++ b/src/configs/inputs/pad_xbox360.ts @@ -1,5 +1,5 @@ -import {SettingGamepad} from "../../system/settings/settings-gamepad"; -import {Button} from "#enums/buttons"; +import { SettingGamepad } from "../../system/settings/settings-gamepad"; +import { Button } from "#enums/buttons"; /** * Generic pad mapping diff --git a/src/data/ability.ts b/src/data/ability.ts index 8a7365b2c28..33f6e0522f7 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -118,6 +118,14 @@ export class Ability implements Localizable { this.nameAppend += " (N)"; return this; } + + /** + * Internal flag used for developers to document edge cases. When using this, please be sure to document the edge case. + * @returns the ability + */ + edgeCase(): this { + return this; + } } type AbAttrApplyFunc = (attr: TAttr, passive: boolean) => boolean | Promise; @@ -162,7 +170,7 @@ export class BlockRecoilDamageAttr extends AbAttr { } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]) { - return i18next.t("abilityTriggers:blockRecoilDamage", {pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName}); + return i18next.t("abilityTriggers:blockRecoilDamage", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName }); } } @@ -634,15 +642,15 @@ export class ReverseDrainAbAttr extends PostDefendAbAttr { * Examples include: Absorb, Draining Kiss, Bitter Blade, etc. * Also displays a message to show this ability was activated. * @param pokemon {@linkcode Pokemon} with this ability - * @param passive N/A + * @param _passive N/A * @param attacker {@linkcode Pokemon} that is attacking this Pokemon * @param move {@linkcode PokemonMove} that is being used - * @param hitResult N/A - * @args N/A + * @param _hitResult N/A + * @param _args N/A * @returns true if healing should be reversed on a healing move, false otherwise. */ - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (move.hasAttr(HitHealAttr)) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (move.hasAttr(HitHealAttr) && !move.hitsSubstitute(attacker, pokemon)) { if (!simulated) { pokemon.scene.queueMessage(i18next.t("abilityTriggers:reverseDrain", { pokemonNameWithAffix: getPokemonNameWithAffix(attacker) })); } @@ -669,8 +677,8 @@ export class PostDefendStatStageChangeAbAttr extends PostDefendAbAttr { this.allOthers = allOthers; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (this.condition(pokemon, attacker, move)) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) { if (simulated) { return true; } @@ -707,13 +715,13 @@ export class PostDefendHpGatedStatStageChangeAbAttr extends PostDefendAbAttr { this.selfTarget = selfTarget; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - const hpGateFlat: integer = Math.ceil(pokemon.getMaxHp() * this.hpGate); + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + const hpGateFlat: number = Math.ceil(pokemon.getMaxHp() * this.hpGate); const lastAttackReceived = pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1]; const damageReceived = lastAttackReceived?.damage || 0; - if (this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat)) { - if (!simulated ) { + if (this.condition(pokemon, attacker, move) && (pokemon.hp <= hpGateFlat && (pokemon.hp + damageReceived) > hpGateFlat) && !move.hitsSubstitute(attacker, pokemon)) { + if (!simulated) { pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, (this.selfTarget ? pokemon : attacker).getBattlerIndex(), true, this.stats, this.stages)); } return true; @@ -734,8 +742,8 @@ export class PostDefendApplyArenaTrapTagAbAttr extends PostDefendAbAttr { this.tagType = tagType; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (this.condition(pokemon, attacker, move)) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) { const tag = pokemon.scene.arena.getTag(this.tagType) as ArenaTrapTag; if (!pokemon.scene.arena.getTag(this.tagType) || tag.layers < tag.maxLayers) { if (!simulated) { @@ -758,8 +766,8 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr { this.tagType = tagType; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (this.condition(pokemon, attacker, move)) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) { if (!pokemon.getTag(this.tagType) && !simulated) { pokemon.addTag(this.tagType, undefined, undefined, pokemon.id); pokemon.scene.queueMessage(i18next.t("abilityTriggers:windPowerCharged", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name })); @@ -771,8 +779,8 @@ export class PostDefendApplyBattlerTagAbAttr extends PostDefendAbAttr { } export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (hitResult < HitResult.NO_EFFECT) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): boolean { + if (hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon)) { if (simulated) { return true; } @@ -787,7 +795,7 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { return i18next.t("abilityTriggers:postDefendTypeChange", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName, @@ -805,8 +813,8 @@ export class PostDefendTerrainChangeAbAttr extends PostDefendAbAttr { this.terrainType = terrainType; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (hitResult < HitResult.NO_EFFECT) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): boolean { + if (hitResult < HitResult.NO_EFFECT && !move.hitsSubstitute(attacker, pokemon)) { if (simulated) { return pokemon.scene.arena.terrain?.terrainType !== (this.terrainType || undefined); } else { @@ -829,8 +837,9 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { this.effects = effects; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.status + && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance) && !move.hitsSubstitute(attacker, pokemon)) { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randSeedInt(this.effects.length)]; if (simulated) { return attacker.canSetStatus(effect, true, false, pokemon); @@ -869,8 +878,8 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { this.turnCount = turnCount; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && pokemon.randSeedInt(100) < this.chance && !move.hitsSubstitute(attacker, pokemon)) { if (simulated) { return attacker.canAddTag(this.tagType); } else { @@ -893,7 +902,11 @@ export class PostDefendCritStatStageChangeAbAttr extends PostDefendAbAttr { this.stages = stages; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (move.hitsSubstitute(attacker, pokemon)) { + return false; + } + if (!simulated) { pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ this.stat ], this.stages)); } @@ -901,7 +914,7 @@ export class PostDefendCritStatStageChangeAbAttr extends PostDefendAbAttr { return true; } - getCondition(): AbAttrCondition { + override getCondition(): AbAttrCondition { return (pokemon: Pokemon) => pokemon.turnData.attacksReceived.length !== 0 && pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1].critical; } } @@ -915,8 +928,9 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { this.damageRatio = damageRatio; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (!simulated && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (!simulated && move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) + && !attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr) && !move.hitsSubstitute(attacker, pokemon)) { attacker.damageAndUpdate(Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), HitResult.OTHER); attacker.turnData.damageTaken += Utils.toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)); return true; @@ -925,7 +939,7 @@ export class PostDefendContactDamageAbAttr extends PostDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { return i18next.t("abilityTriggers:postDefendContactDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName @@ -948,8 +962,8 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr { this.turns = turns; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !move.hitsSubstitute(attacker, pokemon)) { if (pokemon.getTag(BattlerTagType.PERISH_SONG) || attacker.getTag(BattlerTagType.PERISH_SONG)) { return false; } else { @@ -963,24 +977,24 @@ export class PostDefendPerishSongAbAttr extends PostDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return i18next.t("abilityTriggers:perishBody", {pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName}); + override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { + return i18next.t("abilityTriggers:perishBody", { pokemonName: getPokemonNameWithAffix(pokemon), abilityName: abilityName }); } } export class PostDefendWeatherChangeAbAttr extends PostDefendAbAttr { private weatherType: WeatherType; - protected condition: PokemonDefendCondition | null; + protected condition?: PokemonDefendCondition; constructor(weatherType: WeatherType, condition?: PokemonDefendCondition) { super(); this.weatherType = weatherType; - this.condition = condition ?? null; + this.condition = condition; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (this.condition !== null && !this.condition(pokemon, attacker, move)) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (this.condition && !this.condition(pokemon, attacker, move) || move.hitsSubstitute(attacker, pokemon)) { return false; } if (!pokemon.scene.arena.weather?.isImmutable()) { @@ -999,8 +1013,9 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr { super(); } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr)) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) + && !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr) && !move.hitsSubstitute(attacker, pokemon)) { if (!simulated) { const tempAbilityId = attacker.getAbility().id; attacker.summonData.ability = pokemon.getAbility().id; @@ -1012,7 +1027,7 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + override getTriggerMessage(pokemon: Pokemon, _abilityName: string, ..._args: any[]): string { return i18next.t("abilityTriggers:postDefendAbilitySwap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }); } } @@ -1025,8 +1040,9 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr { this.ability = ability; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr)) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr) + && !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr) && !move.hitsSubstitute(attacker, pokemon)) { if (!simulated) { attacker.summonData.ability = this.ability; } @@ -1037,7 +1053,7 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr { return false; } - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + override getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { return i18next.t("abilityTriggers:postDefendAbilityGive", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName @@ -1056,8 +1072,8 @@ export class PostDefendMoveDisableAbAttr extends PostDefendAbAttr { this.chance = chance; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): boolean { - if (attacker.getTag(BattlerTagType.DISABLED) === null) { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _hitResult: HitResult, _args: any[]): boolean { + if (attacker.getTag(BattlerTagType.DISABLED) === null && !move.hitsSubstitute(attacker, pokemon)) { if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && (this.chance === -1 || pokemon.randSeedInt(100) < this.chance)) { if (simulated) { return true; @@ -1268,7 +1284,7 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr { if (pokemon.getTypes().some((t) => t !== moveType)) { if (!simulated) { this.moveType = moveType; - pokemon.summonData.types = [moveType]; + pokemon.summonData.types = [ moveType ]; pokemon.updateInfo(); } @@ -1724,17 +1740,17 @@ export class PostAttackApplyBattlerTagAbAttr extends PostAttackAbAttr { } export class PostDefendStealHeldItemAbAttr extends PostDefendAbAttr { - private condition: PokemonDefendCondition | null; + private condition?: PokemonDefendCondition; constructor(condition?: PokemonDefendCondition) { super(); - this.condition = condition ?? null; + this.condition = condition; } - applyPostDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, args: any[]): Promise { + override applyPostDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, hitResult: HitResult, _args: any[]): Promise { return new Promise(resolve => { - if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move))) { + if (!simulated && hitResult < HitResult.NO_EFFECT && (!this.condition || this.condition(pokemon, attacker, move)) && !move.hitsSubstitute(attacker, pokemon)) { const heldItems = this.getTargetHeldItems(attacker).filter(i => i.isTransferable); if (heldItems.length) { const stolenItem = heldItems[pokemon.randSeedInt(heldItems.length)]; @@ -2563,24 +2579,24 @@ export class PreSwitchOutClearWeatherAbAttr extends PreSwitchOutAbAttr { // Clear weather only if user's ability matches the weather and no other pokemon has the ability. switch (weatherType) { - case (WeatherType.HARSH_SUN): - if (pokemon.hasAbility(Abilities.DESOLATE_LAND) + case (WeatherType.HARSH_SUN): + if (pokemon.hasAbility(Abilities.DESOLATE_LAND) && pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) { - turnOffWeather = true; - } - break; - case (WeatherType.HEAVY_RAIN): - if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA) + turnOffWeather = true; + } + break; + case (WeatherType.HEAVY_RAIN): + if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA) && pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) { - turnOffWeather = true; - } - break; - case (WeatherType.STRONG_WINDS): - if (pokemon.hasAbility(Abilities.DELTA_STREAM) + turnOffWeather = true; + } + break; + case (WeatherType.STRONG_WINDS): + if (pokemon.hasAbility(Abilities.DELTA_STREAM) && pokemon.scene.getField(true).filter(p => p !== pokemon).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) { - turnOffWeather = true; - } - break; + turnOffWeather = true; + } + break; } if (simulated) { @@ -2814,7 +2830,7 @@ export class PreApplyBattlerTagImmunityAbAttr extends PreApplyBattlerTagAbAttr { constructor(immuneTagTypes: BattlerTagType | BattlerTagType[]) { super(); - this.immuneTagTypes = Array.isArray(immuneTagTypes) ? immuneTagTypes : [immuneTagTypes]; + this.immuneTagTypes = Array.isArray(immuneTagTypes) ? immuneTagTypes : [ immuneTagTypes ]; } applyPreApplyBattlerTag(pokemon: Pokemon, passive: boolean, simulated: boolean, tag: BattlerTag, cancelled: Utils.BooleanHolder, args: any[]): boolean { @@ -3099,17 +3115,17 @@ function getAnticipationCondition(): AbAttrCondition { // edge case for hidden power, type is computed if (move.getMove().id === Moves.HIDDEN_POWER) { const iv_val = Math.floor(((opponent.ivs[Stat.HP] & 1) - +(opponent.ivs[Stat.ATK] & 1) * 2 - +(opponent.ivs[Stat.DEF] & 1) * 4 - +(opponent.ivs[Stat.SPD] & 1) * 8 - +(opponent.ivs[Stat.SPATK] & 1) * 16 - +(opponent.ivs[Stat.SPDEF] & 1) * 32) * 15/63); + + (opponent.ivs[Stat.ATK] & 1) * 2 + + (opponent.ivs[Stat.DEF] & 1) * 4 + + (opponent.ivs[Stat.SPD] & 1) * 8 + + (opponent.ivs[Stat.SPATK] & 1) * 16 + + (opponent.ivs[Stat.SPDEF] & 1) * 32) * 15 / 63); const type = [ Type.FIGHTING, Type.FLYING, Type.POISON, Type.GROUND, Type.ROCK, Type.BUG, Type.GHOST, Type.STEEL, Type.FIRE, Type.WATER, Type.GRASS, Type.ELECTRIC, - Type.PSYCHIC, Type.ICE, Type.DRAGON, Type.DARK][iv_val]; + Type.PSYCHIC, Type.ICE, Type.DRAGON, Type.DARK ][iv_val]; if (pokemon.getAttackTypeEffectiveness(type, opponent) >= 2) { return true; @@ -3644,7 +3660,7 @@ export class PostTurnHurtIfSleepingAbAttr extends PostTurnAbAttr { if ((opp.status?.effect === StatusEffect.SLEEP || opp.hasAbility(Abilities.COMATOSE)) && !opp.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { if (!simulated) { opp.damageAndUpdate(Utils.toDmgValue(opp.getMaxHp() / 8), HitResult.OTHER); - pokemon.scene.queueMessage(i18next.t("abilityTriggers:badDreams", {pokemonName: getPokemonNameWithAffix(opp)})); + pokemon.scene.queueMessage(i18next.t("abilityTriggers:badDreams", { pokemonName: getPokemonNameWithAffix(opp) })); } hadEffect = true; } @@ -3755,8 +3771,8 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr { */ applyPostMoveUsed(dancer: Pokemon, move: PokemonMove, source: Pokemon, targets: BattlerIndex[], simulated: boolean, args: any[]): boolean | Promise { // List of tags that prevent the Dancer from replicating the move - const forbiddenTags = [BattlerTagType.FLYING, BattlerTagType.UNDERWATER, - BattlerTagType.UNDERGROUND, BattlerTagType.HIDDEN]; + const forbiddenTags = [ BattlerTagType.FLYING, BattlerTagType.UNDERWATER, + BattlerTagType.UNDERGROUND, BattlerTagType.HIDDEN ]; // The move to replicate cannot come from the Dancer if (source.getBattlerIndex() !== dancer.getBattlerIndex() && !dancer.summonData.tags.some(tag => forbiddenTags.includes(tag.tagType))) { @@ -3767,7 +3783,7 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr { dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, target, move, true, true)); } else if (move.getMove() instanceof SelfStatusMove) { // If the move is a SelfStatusMove (ie. Swords Dance) the Dancer should replicate it on itself - dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, [dancer.getBattlerIndex()], move, true, true)); + dancer.scene.unshiftPhase(new MovePhase(dancer.scene, dancer, [ dancer.getBattlerIndex() ], move, true, true)); } } return true; @@ -3784,9 +3800,9 @@ export class PostDancingMoveAbAttr extends PostMoveUsedAbAttr { */ getTarget(dancer: Pokemon, source: Pokemon, targets: BattlerIndex[]) : BattlerIndex[] { if (dancer.isPlayer()) { - return source.isPlayer() ? targets : [source.getBattlerIndex()]; + return source.isPlayer() ? targets : [ source.getBattlerIndex() ]; } - return source.isPlayer() ? [source.getBattlerIndex()] : targets; + return source.isPlayer() ? [ source.getBattlerIndex() ] : targets; } } @@ -4063,24 +4079,24 @@ export class PostFaintClearWeatherAbAttr extends PostFaintAbAttr { // Clear weather only if user's ability matches the weather and no other pokemon has the ability. switch (weatherType) { - case (WeatherType.HARSH_SUN): - if (pokemon.hasAbility(Abilities.DESOLATE_LAND) + case (WeatherType.HARSH_SUN): + if (pokemon.hasAbility(Abilities.DESOLATE_LAND) && pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DESOLATE_LAND)).length === 0) { - turnOffWeather = true; - } - break; - case (WeatherType.HEAVY_RAIN): - if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA) + turnOffWeather = true; + } + break; + case (WeatherType.HEAVY_RAIN): + if (pokemon.hasAbility(Abilities.PRIMORDIAL_SEA) && pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.PRIMORDIAL_SEA)).length === 0) { - turnOffWeather = true; - } - break; - case (WeatherType.STRONG_WINDS): - if (pokemon.hasAbility(Abilities.DELTA_STREAM) + turnOffWeather = true; + } + break; + case (WeatherType.STRONG_WINDS): + if (pokemon.hasAbility(Abilities.DELTA_STREAM) && pokemon.scene.getField(true).filter(p => p.hasAbility(Abilities.DELTA_STREAM)).length === 0) { - turnOffWeather = true; - } - break; + turnOffWeather = true; + } + break; } if (simulated) { @@ -4476,7 +4492,7 @@ export class PostSummonStatStageChangeOnArenaAbAttr extends PostSummonStatStageC export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { private multiplier: number; private tagType: BattlerTagType; - private recoilDamageFunc: ((pokemon: Pokemon) => number) | undefined; + private recoilDamageFunc?: ((pokemon: Pokemon) => number); private triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string; constructor(condition: PokemonDefendCondition, multiplier: number, tagType: BattlerTagType, triggerMessageFunc: (pokemon: Pokemon, abilityName: string) => string, recoilDamageFunc?: (pokemon: Pokemon) => number) { @@ -4492,16 +4508,16 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { * Applies the pre-defense ability to the Pokémon. * Removes the appropriate `BattlerTagType` when hit by an attack and is in its defense form. * - * @param {Pokemon} pokemon The Pokémon with the ability. - * @param {boolean} passive n/a - * @param {Pokemon} attacker The attacking Pokémon. - * @param {PokemonMove} move The move being used. - * @param {Utils.BooleanHolder} cancelled n/a - * @param {any[]} args Additional arguments. - * @returns {boolean} Whether the immunity was applied. + * @param pokemon The Pokémon with the ability. + * @param _passive n/a + * @param attacker The attacking Pokémon. + * @param move The move being used. + * @param _cancelled n/a + * @param args Additional arguments. + * @returns `true` if the immunity was applied. */ - applyPreDefend(pokemon: Pokemon, passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { - if (this.condition(pokemon, attacker, move)) { + override applyPreDefend(pokemon: Pokemon, _passive: boolean, simulated: boolean, attacker: Pokemon, move: Move, _cancelled: Utils.BooleanHolder, args: any[]): boolean { + if (this.condition(pokemon, attacker, move) && !move.hitsSubstitute(attacker, pokemon)) { if (!simulated) { (args[0] as Utils.NumberHolder).value = this.multiplier; pokemon.removeTag(this.tagType); @@ -4517,12 +4533,12 @@ export class FormBlockDamageAbAttr extends ReceivedMoveDamageMultiplierAbAttr { /** * Gets the message triggered when the Pokémon avoids damage using the form-changing ability. - * @param {Pokemon} pokemon The Pokémon with the ability. - * @param {string} abilityName The name of the ability. - * @param {...any} args n/a - * @returns {string} The trigger message. + * @param pokemon The Pokémon with the ability. + * @param abilityName The name of the ability. + * @param _args n/a + * @returns The trigger message. */ - getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { + getTriggerMessage(pokemon: Pokemon, abilityName: string, ..._args: any[]): string { return this.triggerMessageFunc(pokemon, abilityName); } } @@ -4561,7 +4577,7 @@ export class BypassSpeedChanceAbAttr extends AbAttr { const turnCommand = pokemon.scene.currentBattle.turnCommands[pokemon.getBattlerIndex()]; const isCommandFight = turnCommand?.command === Command.FIGHT; - const move = turnCommand?.move?.move ?allMoves[turnCommand.move.move] : null; + const move = turnCommand?.move?.move ? allMoves[turnCommand.move.move] : null; const isDamageMove = move?.category === MoveCategory.PHYSICAL || move?.category === MoveCategory.SPECIAL; if (isCommandFight && isDamageMove) { @@ -4574,7 +4590,7 @@ export class BypassSpeedChanceAbAttr extends AbAttr { } getTriggerMessage(pokemon: Pokemon, abilityName: string, ...args: any[]): string { - return i18next.t("abilityTriggers:quickDraw", {pokemonName: getPokemonNameWithAffix(pokemon)}); + return i18next.t("abilityTriggers:quickDraw", { pokemonName: getPokemonNameWithAffix(pokemon) }); } } @@ -4622,8 +4638,8 @@ async function applyAbAttrsInternal( simulated: boolean = false, messages: string[] = [], ) { - for (const passive of [false, true]) { - if (!pokemon?.canApplyAbility(passive)) { + for (const passive of [ false, true ]) { + if (!pokemon?.canApplyAbility(passive) || (passive && pokemon.getPassiveAbility().id === pokemon.getAbility().id)) { continue; } @@ -4872,7 +4888,7 @@ export function initAbilities() { .attr(TypeImmunityHealAbAttr, Type.WATER) .ignorable(), new Ability(Abilities.OBLIVIOUS, 3) - .attr(BattlerTagImmunityAbAttr, [BattlerTagType.INFATUATED, BattlerTagType.TAUNT]) + .attr(BattlerTagImmunityAbAttr, [ BattlerTagType.INFATUATED, BattlerTagType.TAUNT ]) .attr(IntimidateImmunityAbAttr) .ignorable(), new Ability(Abilities.CLOUD_NINE, 3) @@ -4897,8 +4913,7 @@ export function initAbilities() { .attr(TypeImmunityAddBattlerTagAbAttr, Type.FIRE, BattlerTagType.FIRE_BOOST, 1) .ignorable(), new Ability(Abilities.SHIELD_DUST, 3) - .attr(IgnoreMoveEffectsAbAttr) - .partial(), + .attr(IgnoreMoveEffectsAbAttr), new Ability(Abilities.OWN_TEMPO, 3) .attr(BattlerTagImmunityAbAttr, BattlerTagType.CONFUSED) .attr(IntimidateImmunityAbAttr) @@ -4942,8 +4957,7 @@ export function initAbilities() { .attr(TypeImmunityStatStageChangeAbAttr, Type.ELECTRIC, Stat.SPATK, 1) .ignorable(), new Ability(Abilities.SERENE_GRACE, 3) - .attr(MoveEffectChanceMultiplierAbAttr, 2) - .partial(), + .attr(MoveEffectChanceMultiplierAbAttr, 2), new Ability(Abilities.SWIFT_SWIM, 3) .attr(StatMultiplierAbAttr, Stat.SPD, 2) .condition(getWeatherCondition(WeatherType.RAIN, WeatherType.HEAVY_RAIN)), @@ -5017,10 +5031,10 @@ export function initAbilities() { new Ability(Abilities.CUTE_CHARM, 3) .attr(PostDefendContactApplyTagChanceAbAttr, 30, BattlerTagType.INFATUATED), new Ability(Abilities.PLUS, 3) - .conditionalAttr(p => p.scene.currentBattle.double && [Abilities.PLUS, Abilities.MINUS].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5) + .conditionalAttr(p => p.scene.currentBattle.double && [ Abilities.PLUS, Abilities.MINUS ].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5) .ignorable(), new Ability(Abilities.MINUS, 3) - .conditionalAttr(p => p.scene.currentBattle.double && [Abilities.PLUS, Abilities.MINUS].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5) + .conditionalAttr(p => p.scene.currentBattle.double && [ Abilities.PLUS, Abilities.MINUS ].some(a => p.getAlly().hasAbility(a)), StatMultiplierAbAttr, Stat.SPATK, 1.5) .ignorable(), new Ability(Abilities.FORECAST, 3) .attr(UncopiableAbilityAbAttr) @@ -5138,7 +5152,7 @@ export function initAbilities() { .conditionalAttr(pokemon => !!pokemon.status || pokemon.hasAbility(Abilities.COMATOSE), StatMultiplierAbAttr, Stat.SPD, 1.5), new Ability(Abilities.NORMALIZE, 4) .attr(MoveTypeChangeAbAttr, Type.NORMAL, 1.2, (user, target, move) => { - return ![Moves.HIDDEN_POWER, Moves.WEATHER_BALL, Moves.NATURAL_GIFT, Moves.JUDGMENT, Moves.TECHNO_BLAST].includes(move.id); + return ![ Moves.HIDDEN_POWER, Moves.WEATHER_BALL, Moves.NATURAL_GIFT, Moves.JUDGMENT, Moves.TECHNO_BLAST ].includes(move.id); }), new Ability(Abilities.SNIPER, 4) .attr(MultCritAbAttr, 1.5), @@ -5184,7 +5198,7 @@ export function initAbilities() { new Ability(Abilities.SLOW_START, 4) .attr(PostSummonAddBattlerTagAbAttr, BattlerTagType.SLOW_START, 5), new Ability(Abilities.SCRAPPY, 4) - .attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING]) + .attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ]) .attr(IntimidateImmunityAbAttr), new Ability(Abilities.STORM_DRAIN, 4) .attr(RedirectTypeMoveAbAttr, Type.WATER) @@ -5225,16 +5239,17 @@ export function initAbilities() { .attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT)) .condition(getSheerForceHitDisableAbCondition()), new Ability(Abilities.SHEER_FORCE, 5) - .attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461/4096) + .attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461 / 4096) .attr(MoveEffectChanceMultiplierAbAttr, 0) - .partial(), + .edgeCase() // Should disable shell bell and Meloetta's relic song transformation + .edgeCase(), // Should disable life orb, eject button, red card, kee/maranga berry if they get implemented new Ability(Abilities.CONTRARY, 5) .attr(StatStageChangeMultiplierAbAttr, -1) .ignorable(), new Ability(Abilities.UNNERVE, 5) .attr(PreventBerryUseAbAttr), new Ability(Abilities.DEFIANT, 5) - .attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [Stat.ATK], 2), + .attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [ Stat.ATK ], 2), new Ability(Abilities.DEFEATIST, 5) .attr(StatMultiplierAbAttr, Stat.ATK, 0.5) .attr(StatMultiplierAbAttr, Stat.SPATK, 0.5) @@ -5270,7 +5285,7 @@ export function initAbilities() { /** Rate is doubled when under sun {@link https://dex.pokemonshowdown.com/abilities/harvest} */ (pokemon) => 0.5 * (getWeatherCondition(WeatherType.SUNNY, WeatherType.HARSH_SUN)(pokemon) ? 2 : 1) ) - .partial(), + .edgeCase(), // Cannot recover berries used up by fling or natural gift (unimplemented) new Ability(Abilities.TELEPATHY, 5) .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon.getAlly() === attacker && move instanceof AttackMove) .ignorable(), @@ -5320,7 +5335,7 @@ export function initAbilities() { return move.category !== MoveCategory.STATUS && (moveType === Type.DARK || moveType === Type.BUG || moveType === Type.GHOST); }, Stat.SPD, 1) - .attr(PostIntimidateStatStageChangeAbAttr, [Stat.SPD], 1), + .attr(PostIntimidateStatStageChangeAbAttr, [ Stat.SPD ], 1), new Ability(Abilities.MAGIC_BOUNCE, 5) .ignorable() .unimplemented(), @@ -5349,7 +5364,7 @@ export function initAbilities() { .bypassFaint(), new Ability(Abilities.VICTORY_STAR, 5) .attr(StatMultiplierAbAttr, Stat.ACC, 1.1) - .partial(), + .partial(), // Does not boost ally's accuracy new Ability(Abilities.TURBOBLAZE, 5) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonTurboblaze", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })) .attr(MoveAbilityBypassAbAttr), @@ -5357,12 +5372,12 @@ export function initAbilities() { .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonTeravolt", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })) .attr(MoveAbilityBypassAbAttr), new Ability(Abilities.AROMA_VEIL, 6) - .attr(UserFieldBattlerTagImmunityAbAttr, [BattlerTagType.INFATUATED, BattlerTagType.TAUNT, BattlerTagType.DISABLED, BattlerTagType.TORMENT, BattlerTagType.HEAL_BLOCK]), + .attr(UserFieldBattlerTagImmunityAbAttr, [ BattlerTagType.INFATUATED, BattlerTagType.TAUNT, BattlerTagType.DISABLED, BattlerTagType.TORMENT, BattlerTagType.HEAL_BLOCK ]), new Ability(Abilities.FLOWER_VEIL, 6) .ignorable() .unimplemented(), new Ability(Abilities.CHEEK_POUCH, 6) - .attr(HealFromBerryUseAbAttr, 1/3), + .attr(HealFromBerryUseAbAttr, 1 / 3), new Ability(Abilities.PROTEAN, 6) .attr(PokemonTypeChangeAbAttr), //.condition((p) => !p.summonData?.abilitiesApplied.includes(Abilities.PROTEAN)), //Gen 9 Implementation @@ -5375,7 +5390,7 @@ export function initAbilities() { .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.hasFlag(MoveFlags.BALLBOMB_MOVE)) .ignorable(), new Ability(Abilities.COMPETITIVE, 6) - .attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [Stat.SPATK], 2), + .attr(PostStatStageChangeStatStageChangeAbAttr, (target, statsChanged, stages) => stages < 0, [ Stat.SPATK ], 2), new Ability(Abilities.STRONG_JAW, 6) .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.BITING_MOVE), 1.5), new Ability(Abilities.REFRIGERATE, 6) @@ -5460,7 +5475,7 @@ export function initAbilities() { .attr(UnsuppressableAbilityAbAttr) .attr(NoFusionAbilityAbAttr) .bypassFaint() - .partial(), + .partial(), // Meteor form should protect against status effects and yawn new Ability(Abilities.STAKEOUT, 7) .attr(MovePowerBoostAbAttr, (user, target, move) => user?.scene.currentBattle.turnCommands[target?.getBattlerIndex() ?? BattlerIndex.ATTACKER]?.command === Command.POKEMON, 2), new Ability(Abilities.WATER_BUBBLE, 7) @@ -5471,7 +5486,7 @@ export function initAbilities() { new Ability(Abilities.STEELWORKER, 7) .attr(MoveTypePowerBoostAbAttr, Type.STEEL), new Ability(Abilities.BERSERK, 7) - .attr(PostDefendHpGatedStatStageChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [Stat.SPATK], 1) + .attr(PostDefendHpGatedStatStageChangeAbAttr, (target, user, move) => move.category !== MoveCategory.STATUS, 0.5, [ Stat.SPATK ], 1) .condition(getSheerForceHitDisableAbCondition()), new Ability(Abilities.SLUSH_RUSH, 7) .attr(StatMultiplierAbAttr, Stat.SPD, 2) @@ -5503,7 +5518,8 @@ export function initAbilities() { .attr(NoFusionAbilityAbAttr) // Add BattlerTagType.DISGUISE if the pokemon is in its disguised form .conditionalAttr(pokemon => pokemon.formIndex === 0, PostSummonAddBattlerTagAbAttr, BattlerTagType.DISGUISE, 0, false) - .attr(FormBlockDamageAbAttr, (target, user, move) => !!target.getTag(BattlerTagType.DISGUISE) && target.getMoveEffectiveness(user, move) > 0, 0, BattlerTagType.DISGUISE, + .attr(FormBlockDamageAbAttr, + (target, user, move) => !!target.getTag(BattlerTagType.DISGUISE) && target.getMoveEffectiveness(user, move) > 0, 0, BattlerTagType.DISGUISE, (pokemon, abilityName) => i18next.t("abilityTriggers:disguiseAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName }), (pokemon) => Utils.toDmgValue(pokemon.getMaxHp() / 8)) .attr(PostBattleInitFormChangeAbAttr, () => 0) @@ -5517,19 +5533,21 @@ export function initAbilities() { .attr(UnsuppressableAbilityAbAttr) .attr(NoFusionAbilityAbAttr) .bypassFaint(), - new Ability(Abilities.POWER_CONSTRUCT, 7) // TODO: 10% Power Construct Zygarde isn't accounted for yet. If changed, update Zygarde's getSpeciesFormIndex entry accordingly - .attr(PostBattleInitFormChangeAbAttr, () => 2) - .attr(PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2) - .attr(PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2) + new Ability(Abilities.POWER_CONSTRUCT, 7) + .conditionalAttr(pokemon => pokemon.formIndex === 2 || pokemon.formIndex === 4, PostBattleInitFormChangeAbAttr, () => 2) + .conditionalAttr(pokemon => pokemon.formIndex === 3 || pokemon.formIndex === 5, PostBattleInitFormChangeAbAttr, () => 3) + .conditionalAttr(pokemon => pokemon.formIndex === 2 || pokemon.formIndex === 4, PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2) + .conditionalAttr(pokemon => pokemon.formIndex === 2 || pokemon.formIndex === 4, PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "complete" ? 4 : 2) + .conditionalAttr(pokemon => pokemon.formIndex === 3 || pokemon.formIndex === 5, PostSummonFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "10-complete" ? 5 : 3) + .conditionalAttr(pokemon => pokemon.formIndex === 3 || pokemon.formIndex === 5, PostTurnFormChangeAbAttr, p => p.getHpRatio() <= 0.5 || p.getFormKey() === "10-complete" ? 5 : 3) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(UnsuppressableAbilityAbAttr) .attr(NoFusionAbilityAbAttr) - .bypassFaint() - .partial(), - new Ability(Abilities.CORROSION, 7) // TODO: Test Corrosion against Magic Bounce once it is implemented - .attr(IgnoreTypeStatusEffectImmunityAbAttr, [StatusEffect.POISON, StatusEffect.TOXIC], [Type.STEEL, Type.POISON]) - .partial(), + .bypassFaint(), + new Ability(Abilities.CORROSION, 7) + .attr(IgnoreTypeStatusEffectImmunityAbAttr, [ StatusEffect.POISON, StatusEffect.TOXIC ], [ Type.STEEL, Type.POISON ]) + .edgeCase(), // Should interact correctly with magic coat/bounce (not yet implemented), fling with toxic orb (not implemented yet), and synchronize (not fully implemented yet) new Ability(Abilities.COMATOSE, 7) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) @@ -5545,7 +5563,7 @@ export function initAbilities() { new Ability(Abilities.DANCER, 7) .attr(PostDancingMoveAbAttr), new Ability(Abilities.BATTERY, 7) - .attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL], 1.3), + .attr(AllyMoveCategoryPowerBoostAbAttr, [ MoveCategory.SPECIAL ], 1.3), new Ability(Abilities.FLUFFY, 7) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 0.5) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => user.getMoveType(move) === Type.FIRE, 2) @@ -5665,17 +5683,18 @@ export function initAbilities() { .conditionalAttr(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW), PostSummonAddBattlerTagAbAttr, BattlerTagType.ICE_FACE, 0) // When weather changes to HAIL or SNOW while pokemon is fielded, add BattlerTagType.ICE_FACE .attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.ICE_FACE, 0, WeatherType.HAIL, WeatherType.SNOW) - .attr(FormBlockDamageAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0, BattlerTagType.ICE_FACE, + .attr(FormBlockDamageAbAttr, + (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0, BattlerTagType.ICE_FACE, (pokemon, abilityName) => i18next.t("abilityTriggers:iceFaceAvoidedDamage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName: abilityName })) .attr(PostBattleInitFormChangeAbAttr, () => 0) .bypassFaint() .ignorable(), new Ability(Abilities.POWER_SPOT, 8) - .attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL], 1.3), + .attr(AllyMoveCategoryPowerBoostAbAttr, [ MoveCategory.SPECIAL, MoveCategory.PHYSICAL ], 1.3), new Ability(Abilities.MIMICRY, 8) .unimplemented(), new Ability(Abilities.SCREEN_CLEANER, 8) - .attr(PostSummonRemoveArenaTagAbAttr, [ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.REFLECT]), + .attr(PostSummonRemoveArenaTagAbAttr, [ ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.REFLECT ]), new Ability(Abilities.STEELY_SPIRIT, 8) .attr(UserFieldMoveTypePowerBoostAbAttr, Type.STEEL), new Ability(Abilities.PERISH_BODY, 8) @@ -5683,7 +5702,7 @@ export function initAbilities() { new Ability(Abilities.WANDERING_SPIRIT, 8) .attr(PostDefendAbilitySwapAbAttr) .bypassFaint() - .partial(), + .edgeCase(), // interacts incorrectly with rock head. It's meant to switch abilities before recoil would apply so that a pokemon with rock head would lose rock head first and still take the recoil new Ability(Abilities.GORILLA_TACTICS, 8) .attr(GorillaTacticsAbAttr), new Ability(Abilities.NEUTRALIZING_GAS, 8) @@ -5692,7 +5711,7 @@ export function initAbilities() { .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) .attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonNeutralizingGas", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })) - .partial(), + .partial(), // A bunch of weird interactions with other abilities being suppressed then unsuppressed new Ability(Abilities.PASTEL_VEIL, 8) .attr(PostSummonUserFieldRemoveStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) .attr(UserFieldStatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) @@ -5758,7 +5777,7 @@ export function initAbilities() { .attr(PostSummonStatStageChangeOnArenaAbAttr, ArenaTagType.TAILWIND) .ignorable(), new Ability(Abilities.GUARD_DOG, 9) - .attr(PostIntimidateStatStageChangeAbAttr, [Stat.ATK], 1, true) + .attr(PostIntimidateStatStageChangeAbAttr, [ Stat.ATK ], 1, true) .attr(ForceSwitchOutImmunityAbAttr) .ignorable(), new Ability(Abilities.ROCKY_PAYLOAD, 9) @@ -5797,7 +5816,7 @@ export function initAbilities() { new Ability(Abilities.GOOD_AS_GOLD, 9) .attr(MoveImmunityAbAttr, (pokemon, attacker, move) => pokemon !== attacker && move.category === MoveCategory.STATUS) .ignorable() - .partial(), + .partial(), // Lots of weird interactions with moves and abilities such as negating status moves that target the field new Ability(Abilities.VESSEL_OF_RUIN, 9) .attr(FieldMultiplyStatAbAttr, Stat.SPATK, 0.75) .attr(PostSummonMessageAbAttr, (user) => i18next.t("abilityTriggers:postSummonVesselOfRuin", { pokemonNameWithAffix: getPokemonNameWithAffix(user), statName: i18next.t(getStatKey(Stat.SPATK)) })) @@ -5830,7 +5849,7 @@ export function initAbilities() { .attr(MovePowerBoostAbAttr, (user, target, move) => move.hasFlag(MoveFlags.SLICING_MOVE), 1.5), new Ability(Abilities.SUPREME_OVERLORD, 9) .attr(VariableMovePowerBoostAbAttr, (user, target, move) => 1 + 0.1 * Math.min(user.isPlayer() ? user.scene.currentBattle.playerFaints : user.scene.currentBattle.enemyFaints, 5)) - .partial(), + .partial(), // Counter resets every wave new Ability(Abilities.COSTAR, 9) .attr(PostSummonCopyAllyStatsAbAttr), new Ability(Abilities.TOXIC_DEBRIS, 9) @@ -5847,7 +5866,7 @@ export function initAbilities() { .attr(PreventBypassSpeedChanceAbAttr, (pokemon, move) => move.category === MoveCategory.STATUS) .attr(MoveAbilityBypassAbAttr, (pokemon, move: Move) => move.category === MoveCategory.STATUS), new Ability(Abilities.MINDS_EYE, 9) - .attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [Type.NORMAL, Type.FIGHTING]) + .attr(IgnoreTypeImmunityAbAttr, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ]) .attr(ProtectStatAbAttr, Stat.ACC) .attr(IgnoreOpponentStatStagesAbAttr, [ Stat.EVA ]) .ignorable(), @@ -5863,25 +5882,25 @@ export function initAbilities() { .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) - .partial(), + .partial(), // Ogerpon tera interactions new Ability(Abilities.EMBODY_ASPECT_WELLSPRING, 9) .attr(PostBattleInitStatStageChangeAbAttr, [ Stat.SPDEF ], 1, true) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) - .partial(), + .partial(), // Ogerpon tera interactions new Ability(Abilities.EMBODY_ASPECT_HEARTHFLAME, 9) .attr(PostBattleInitStatStageChangeAbAttr, [ Stat.ATK ], 1, true) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) - .partial(), + .partial(), // Ogerpon tera interactions new Ability(Abilities.EMBODY_ASPECT_CORNERSTONE, 9) .attr(PostBattleInitStatStageChangeAbAttr, [ Stat.DEF ], 1, true) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) .attr(NoTransformAbilityAbAttr) - .partial(), + .partial(), // Ogerpon tera interactions new Ability(Abilities.TERA_SHIFT, 9) .attr(PostSummonFormChangeAbAttr, p => p.getFormKey() ? 0 : 1) .attr(UncopiableAbilityAbAttr) diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 9e121b81fea..6507d34dcfd 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -1,10 +1,10 @@ import { Arena } from "#app/field/arena"; import BattleScene from "#app/battle-scene"; import { Type } from "#app/data/type"; -import * as Utils from "#app/utils"; +import { BooleanHolder, NumberHolder, toDmgValue } from "#app/utils"; import { MoveCategory, allMoves, MoveTarget, IncrementMovePriorityAttr, applyMoveAttrs } from "#app/data/move"; import { getPokemonNameWithAffix } from "#app/messages"; -import Pokemon, { HitResult, PlayerPokemon, PokemonMove, EnemyPokemon } from "#app/field/pokemon"; +import Pokemon, { HitResult, PokemonMove } from "#app/field/pokemon"; import { StatusEffect } from "#app/data/status-effect"; import { BattlerIndex } from "#app/battle"; import { BlockNonDirectDamageAbAttr, ChangeMovePriorityAbAttr, ProtectStatAbAttr, applyAbAttrs } from "#app/data/ability"; @@ -19,6 +19,7 @@ import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; +import { CommonAnimPhase } from "#app/phases/common-anim-phase"; export enum ArenaTagSide { BOTH, @@ -27,22 +28,15 @@ export enum ArenaTagSide { } export abstract class ArenaTag { - public tagType: ArenaTagType; - public turnCount: integer; - public sourceMove?: Moves; - public sourceId?: integer; - public side: ArenaTagSide; + constructor( + public tagType: ArenaTagType, + public turnCount: number, + public sourceMove?: Moves, + public sourceId?: number, + public side: ArenaTagSide = ArenaTagSide.BOTH + ) {} - - constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves | undefined, sourceId?: integer, side: ArenaTagSide = ArenaTagSide.BOTH) { - this.tagType = tagType; - this.turnCount = turnCount; - this.sourceMove = sourceMove; - this.sourceId = sourceId; - this.side = side; - } - - apply(arena: Arena, args: any[]): boolean { + apply(arena: Arena, simulated: boolean, ...args: unknown[]): boolean { return true; } @@ -65,6 +59,44 @@ export abstract class ArenaTag { ? allMoves[this.sourceMove].name : null; } + + /** + * When given a arena tag or json representing one, load the data for it. + * This is meant to be inherited from by any arena tag with custom attributes + * @param {ArenaTag | any} source An arena tag + */ + loadTag(source : ArenaTag | any) : void { + this.turnCount = source.turnCount; + this.sourceMove = source.sourceMove; + this.sourceId = source.sourceId; + this.side = source.side; + } + + /** + * Helper function that retrieves the source Pokemon + * @param scene medium to retrieve the source Pokemon + * @returns The source {@linkcode Pokemon} or `null` if none is found + */ + public getSourcePokemon(scene: BattleScene): Pokemon | null { + return this.sourceId ? scene.getPokemonById(this.sourceId) : null; + } + + /** + * Helper function that retrieves the Pokemon affected + * @param scene - medium to retrieve the involved Pokemon + * @returns list of PlayerPokemon or EnemyPokemon on the field + */ + public getAffectedPokemon(scene: BattleScene): Pokemon[] { + switch (this.side) { + case ArenaTagSide.PLAYER: + return scene.getPlayerField() ?? []; + case ArenaTagSide.ENEMY: + return scene.getEnemyField() ?? []; + case ArenaTagSide.BOTH: + default: + return scene.getField(true) ?? []; + } + } } /** @@ -72,7 +104,7 @@ export abstract class ArenaTag { * Prevents Pokémon on the opposing side from lowering the stats of the Pokémon in the Mist. */ export class MistTag extends ArenaTag { - constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { + constructor(turnCount: number, sourceId: number, side: ArenaTagSide) { super(ArenaTagType.MIST, turnCount, Moves.MIST, sourceId, side); } @@ -90,10 +122,20 @@ export class MistTag extends ArenaTag { } } - apply(arena: Arena, args: any[]): boolean { - (args[0] as Utils.BooleanHolder).value = true; + /** + * Cancels the lowering of stats + * @param arena the {@linkcode Arena} containing this effect + * @param simulated `true` if the effect should be applied quietly + * @param cancelled a {@linkcode BooleanHolder} whose value is set to `true` + * to flag the stat reduction as cancelled + * @returns `true` if a stat reduction was cancelled; `false` otherwise + */ + override apply(arena: Arena, simulated: boolean, cancelled: BooleanHolder): boolean { + cancelled.value = true; - arena.scene.queueMessage(i18next.t("arenaTag:mistApply")); + if (!simulated) { + arena.scene.queueMessage(i18next.t("arenaTag:mistApply")); + } return true; } @@ -116,7 +158,7 @@ export class WeakenMoveScreenTag extends ArenaTag { * @param side - The side (player or enemy) the tag affects. * @param weakenedCategories - The categories of moves that are weakened by this tag. */ - constructor(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, weakenedCategories: MoveCategory[]) { + constructor(tagType: ArenaTagType, turnCount: number, sourceMove: Moves, sourceId: number, side: ArenaTagSide, weakenedCategories: MoveCategory[]) { super(tagType, turnCount, sourceMove, sourceId, side); this.weakenedCategories = weakenedCategories; @@ -125,17 +167,15 @@ export class WeakenMoveScreenTag extends ArenaTag { /** * Applies the weakening effect to the move. * - * @param arena - The arena where the move is applied. - * @param args - The arguments for the move application. - * @param args[0] - The category of the move. - * @param args[1] - A boolean indicating whether it is a double battle. - * @param args[2] - An object of type `Utils.NumberHolder` that holds the damage multiplier - * - * @returns True if the move was weakened, otherwise false. + * @param arena the {@linkcode Arena} where the move is applied. + * @param simulated n/a + * @param moveCategory the attacking move's {@linkcode MoveCategory}. + * @param damageMultiplier A {@linkcode NumberHolder} containing the damage multiplier + * @returns `true` if the attacking move was weakened; `false` otherwise. */ - apply(arena: Arena, args: any[]): boolean { - if (this.weakenedCategories.includes((args[0] as MoveCategory))) { - (args[2] as Utils.NumberHolder).value = (args[1] as boolean) ? 2732/4096 : 0.5; + override apply(arena: Arena, simulated: boolean, moveCategory: MoveCategory, damageMultiplier: NumberHolder): boolean { + if (this.weakenedCategories.includes(moveCategory)) { + damageMultiplier.value = arena.scene.currentBattle.double ? 2732 / 4096 : 0.5; return true; } return false; @@ -147,8 +187,8 @@ export class WeakenMoveScreenTag extends ArenaTag { * Used by {@linkcode Moves.REFLECT} */ class ReflectTag extends WeakenMoveScreenTag { - constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { - super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side, [MoveCategory.PHYSICAL]); + constructor(turnCount: number, sourceId: number, side: ArenaTagSide) { + super(ArenaTagType.REFLECT, turnCount, Moves.REFLECT, sourceId, side, [ MoveCategory.PHYSICAL ]); } onAdd(arena: Arena, quiet: boolean = false): void { @@ -163,8 +203,8 @@ class ReflectTag extends WeakenMoveScreenTag { * Used by {@linkcode Moves.LIGHT_SCREEN} */ class LightScreenTag extends WeakenMoveScreenTag { - constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { - super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side, [MoveCategory.SPECIAL]); + constructor(turnCount: number, sourceId: number, side: ArenaTagSide) { + super(ArenaTagType.LIGHT_SCREEN, turnCount, Moves.LIGHT_SCREEN, sourceId, side, [ MoveCategory.SPECIAL ]); } onAdd(arena: Arena, quiet: boolean = false): void { @@ -179,8 +219,8 @@ class LightScreenTag extends WeakenMoveScreenTag { * Used by {@linkcode Moves.AURORA_VEIL} */ class AuroraVeilTag extends WeakenMoveScreenTag { - constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { - super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL]); + constructor(turnCount: number, sourceId: number, side: ArenaTagSide) { + super(ArenaTagType.AURORA_VEIL, turnCount, Moves.AURORA_VEIL, sourceId, side, [ MoveCategory.SPECIAL, MoveCategory.PHYSICAL ]); } onAdd(arena: Arena, quiet: boolean = false): void { @@ -202,7 +242,7 @@ export class ConditionalProtectTag extends ArenaTag { /** Does this apply to all moves, including those that ignore other forms of protection? */ protected ignoresBypass: boolean; - constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, condition: ProtectConditionFunc, ignoresBypass: boolean = false) { + constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: number, side: ArenaTagSide, condition: ProtectConditionFunc, ignoresBypass: boolean = false) { super(tagType, 1, sourceMove, sourceId, side); this.protectConditionFunc = condition; @@ -217,38 +257,34 @@ export class ConditionalProtectTag extends ArenaTag { onRemove(arena: Arena): void { } /** - * apply(): Checks incoming moves against the condition function + * Checks incoming moves against the condition function * and protects the target if conditions are met - * @param arena The arena containing this tag - * @param args\[0\] (Utils.BooleanHolder) Signals if the move is cancelled - * @param args\[1\] (Pokemon) The Pokemon using the move - * @param args\[2\] (Pokemon) The intended target of the move - * @param args\[3\] (Moves) The parameters to the condition function - * @param args\[4\] (Utils.BooleanHolder) Signals if the applied protection supercedes protection-ignoring effects - * @returns + * @param arena the {@linkcode Arena} containing this tag + * @param simulated `true` if the tag is applied quietly; `false` otherwise. + * @param isProtected a {@linkcode BooleanHolder} used to flag if the move is protected against + * @param attacker the attacking {@linkcode Pokemon} + * @param defender the defending {@linkcode Pokemon} + * @param moveId the {@linkcode Moves | identifier} for the move being used + * @param ignoresProtectBypass a {@linkcode BooleanHolder} used to flag if a protection effect supercedes effects that ignore protection + * @returns `true` if this tag protected against the attack; `false` otherwise */ - apply(arena: Arena, args: any[]): boolean { - const [ cancelled, user, target, moveId, ignoresBypass ] = args; + override apply(arena: Arena, simulated: boolean, isProtected: BooleanHolder, attacker: Pokemon, defender: Pokemon, + moveId: Moves, ignoresProtectBypass: BooleanHolder): boolean { - if (cancelled instanceof Utils.BooleanHolder - && user instanceof Pokemon - && target instanceof Pokemon - && typeof moveId === "number" - && ignoresBypass instanceof Utils.BooleanHolder) { + if ((this.side === ArenaTagSide.PLAYER) === defender.isPlayer() + && this.protectConditionFunc(arena, moveId)) { + if (!isProtected.value) { + isProtected.value = true; + if (!simulated) { + attacker.stopMultiHit(defender); - if ((this.side === ArenaTagSide.PLAYER) === target.isPlayer() - && this.protectConditionFunc(arena, moveId)) { - if (!cancelled.value) { - cancelled.value = true; - user.stopMultiHit(target); - - new CommonBattleAnim(CommonAnim.PROTECT, target).play(arena.scene); - arena.scene.queueMessage(i18next.t("arenaTag:conditionalProtectApply", { moveName: super.getMoveName(), pokemonNameWithAffix: getPokemonNameWithAffix(target) })); + new CommonBattleAnim(CommonAnim.PROTECT, defender).play(arena.scene); + arena.scene.queueMessage(i18next.t("arenaTag:conditionalProtectApply", { moveName: super.getMoveName(), pokemonNameWithAffix: getPokemonNameWithAffix(defender) })); } - - ignoresBypass.value = ignoresBypass.value || this.ignoresBypass; - return true; } + + ignoresProtectBypass.value = ignoresProtectBypass.value || this.ignoresBypass; + return true; } return false; } @@ -264,7 +300,7 @@ export class ConditionalProtectTag extends ArenaTag { */ const QuickGuardConditionFunc: ProtectConditionFunc = (arena, moveId) => { const move = allMoves[moveId]; - const priority = new Utils.IntegerHolder(move.priority); + const priority = new NumberHolder(move.priority); const effectPhase = arena.scene.getCurrentPhase(); if (effectPhase instanceof MoveEffectPhase) { @@ -280,7 +316,7 @@ const QuickGuardConditionFunc: ProtectConditionFunc = (arena, moveId) => { * Condition: The incoming move has increased priority. */ class QuickGuardTag extends ConditionalProtectTag { - constructor(sourceId: integer, side: ArenaTagSide) { + constructor(sourceId: number, side: ArenaTagSide) { super(ArenaTagType.QUICK_GUARD, Moves.QUICK_GUARD, sourceId, side, QuickGuardConditionFunc); } } @@ -296,11 +332,11 @@ const WideGuardConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean = const move = allMoves[moveId]; switch (move.moveTarget) { - case MoveTarget.ALL_ENEMIES: - case MoveTarget.ALL_NEAR_ENEMIES: - case MoveTarget.ALL_OTHERS: - case MoveTarget.ALL_NEAR_OTHERS: - return true; + case MoveTarget.ALL_ENEMIES: + case MoveTarget.ALL_NEAR_ENEMIES: + case MoveTarget.ALL_OTHERS: + case MoveTarget.ALL_NEAR_OTHERS: + return true; } return false; }; @@ -311,7 +347,7 @@ const WideGuardConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean = * can be an ally or enemy. */ class WideGuardTag extends ConditionalProtectTag { - constructor(sourceId: integer, side: ArenaTagSide) { + constructor(sourceId: number, side: ArenaTagSide) { super(ArenaTagType.WIDE_GUARD, Moves.WIDE_GUARD, sourceId, side, WideGuardConditionFunc); } } @@ -333,7 +369,7 @@ const MatBlockConditionFunc: ProtectConditionFunc = (arena, moveId) : boolean => * Condition: The incoming move is a Physical or Special attack move. */ class MatBlockTag extends ConditionalProtectTag { - constructor(sourceId: integer, side: ArenaTagSide) { + constructor(sourceId: number, side: ArenaTagSide) { super(ArenaTagType.MAT_BLOCK, Moves.MAT_BLOCK, sourceId, side, MatBlockConditionFunc); } @@ -371,7 +407,7 @@ const CraftyShieldConditionFunc: ProtectConditionFunc = (arena, moveId) => { * not target all Pokemon or sides of the field. */ class CraftyShieldTag extends ConditionalProtectTag { - constructor(sourceId: integer, side: ArenaTagSide) { + constructor(sourceId: number, side: ArenaTagSide) { super(ArenaTagType.CRAFTY_SHIELD, Moves.CRAFTY_SHIELD, sourceId, side, CraftyShieldConditionFunc, true); } } @@ -383,12 +419,12 @@ class CraftyShieldTag extends ConditionalProtectTag { export class NoCritTag extends ArenaTag { /** * Constructor method for the NoCritTag class - * @param turnCount `integer` the number of turns this effect lasts + * @param turnCount `number` the number of turns this effect lasts * @param sourceMove {@linkcode Moves} the move that created this effect - * @param sourceId `integer` the ID of the {@linkcode Pokemon} that created this effect + * @param sourceId `number` the ID of the {@linkcode Pokemon} that created this effect * @param side {@linkcode ArenaTagSide} the side to which this effect belongs */ - constructor(turnCount: integer, sourceMove: Moves, sourceId: integer, side: ArenaTagSide) { + constructor(turnCount: number, sourceMove: Moves, sourceId: number, side: ArenaTagSide) { super(ArenaTagType.NO_CRIT, turnCount, sourceMove, sourceId, side); } @@ -418,7 +454,7 @@ class WishTag extends ArenaTag { private triggerMessage: string; private healHp: number; - constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { + constructor(turnCount: number, sourceId: number, side: ArenaTagSide) { super(ArenaTagType.WISH, turnCount, Moves.WISH, sourceId, side); } @@ -428,7 +464,7 @@ class WishTag extends ArenaTag { if (user) { this.battlerIndex = user.getBattlerIndex(); this.triggerMessage = i18next.t("arenaTag:wishTagOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(user) }); - this.healHp = Utils.toDmgValue(user.getMaxHp() / 2); + this.healHp = toDmgValue(user.getMaxHp() / 2); } else { console.warn("Failed to get source for WishTag onAdd"); } @@ -459,18 +495,25 @@ export class WeakenMoveTypeTag extends ArenaTag { * @param sourceMove - The move that created the tag. * @param sourceId - The ID of the source of the tag. */ - constructor(tagType: ArenaTagType, turnCount: integer, type: Type, sourceMove: Moves, sourceId: integer) { + constructor(tagType: ArenaTagType, turnCount: number, type: Type, sourceMove: Moves, sourceId: number) { super(tagType, turnCount, sourceMove, sourceId); this.weakenedType = type; } - apply(arena: Arena, args: any[]): boolean { - if ((args[0] as Type) === this.weakenedType) { - (args[1] as Utils.NumberHolder).value *= 0.33; + /** + * Reduces an attack's power by 0.33x if it matches this tag's weakened type. + * @param arena n/a + * @param simulated n/a + * @param type the attack's {@linkcode Type} + * @param power a {@linkcode NumberHolder} containing the attack's power + * @returns `true` if the attack's power was reduced; `false` otherwise. + */ + override apply(arena: Arena, simulated: boolean, type: Type, power: NumberHolder): boolean { + if (type === this.weakenedType) { + power.value *= 0.33; return true; } - return false; } } @@ -480,7 +523,7 @@ export class WeakenMoveTypeTag extends ArenaTag { * Weakens Electric type moves for a set amount of turns, usually 5. */ class MudSportTag extends WeakenMoveTypeTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(ArenaTagType.MUD_SPORT, turnCount, Type.ELECTRIC, Moves.MUD_SPORT, sourceId); } @@ -498,7 +541,7 @@ class MudSportTag extends WeakenMoveTypeTag { * Weakens Fire type moves for a set amount of turns, usually 5. */ class WaterSportTag extends WeakenMoveTypeTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(ArenaTagType.WATER_SPORT, turnCount, Type.FIRE, Moves.WATER_SPORT, sourceId); } @@ -512,15 +555,16 @@ class WaterSportTag extends WeakenMoveTypeTag { } /** - * Arena Tag class for the secondary effect of {@link https://bulbapedia.bulbagarden.net/wiki/Plasma_Fists_(move) | Plasma Fists}. + * Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Ion_Deluge_(move) | Ion Deluge} + * and the secondary effect of {@link https://bulbapedia.bulbagarden.net/wiki/Plasma_Fists_(move) | Plasma Fists}. * Converts Normal-type moves to Electric type for the rest of the turn. */ -export class PlasmaFistsTag extends ArenaTag { - constructor() { - super(ArenaTagType.PLASMA_FISTS, 1, Moves.PLASMA_FISTS); +export class IonDelugeTag extends ArenaTag { + constructor(sourceMove?: Moves) { + super(ArenaTagType.ION_DELUGE, 1, sourceMove); } - /** Queues Plasma Fists' on-add message */ + /** Queues an on-add message */ onAdd(arena: Arena): void { arena.scene.queueMessage(i18next.t("arenaTag:plasmaFistsOnAdd")); } @@ -530,13 +574,12 @@ export class PlasmaFistsTag extends ArenaTag { /** * Converts Normal-type moves to Electric type * @param arena n/a - * @param args - * - `[0]` {@linkcode Utils.NumberHolder} A container with a move's {@linkcode Type} + * @param simulated n/a + * @param moveType a {@linkcode NumberHolder} containing a move's {@linkcode Type} * @returns `true` if the given move type changed; `false` otherwise. */ - apply(arena: Arena, args: any[]): boolean { - const moveType = args[0]; - if (moveType instanceof Utils.NumberHolder && moveType.value === Type.NORMAL) { + override apply(arena: Arena, simulated: boolean, moveType: NumberHolder): boolean { + if (moveType.value === Type.NORMAL) { moveType.value = Type.ELECTRIC; return true; } @@ -548,8 +591,8 @@ export class PlasmaFistsTag extends ArenaTag { * Abstract class to implement arena traps. */ export class ArenaTrapTag extends ArenaTag { - public layers: integer; - public maxLayers: integer; + public layers: number; + public maxLayers: number; /** * Creates a new instance of the ArenaTrapTag class. @@ -560,7 +603,7 @@ export class ArenaTrapTag extends ArenaTag { * @param side - The side (player or enemy) the tag affects. * @param maxLayers - The maximum amount of layers this tag can have. */ - constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: integer, side: ArenaTagSide, maxLayers: integer) { + constructor(tagType: ArenaTagType, sourceMove: Moves, sourceId: number, side: ArenaTagSide, maxLayers: number) { super(tagType, 0, sourceMove, sourceId, side); this.layers = 1; @@ -575,22 +618,34 @@ export class ArenaTrapTag extends ArenaTag { } } - apply(arena: Arena, args: any[]): boolean { - const pokemon = args[0] as Pokemon; + /** + * Activates the hazard effect onto a Pokemon when it enters the field + * @param arena the {@linkcode Arena} containing this tag + * @param simulated if `true`, only checks if the hazard would activate. + * @param pokemon the {@linkcode Pokemon} triggering this hazard + * @returns `true` if this hazard affects the given Pokemon; `false` otherwise. + */ + override apply(arena: Arena, simulated: boolean, pokemon: Pokemon): boolean { if (this.sourceId === pokemon.id || (this.side === ArenaTagSide.PLAYER) !== pokemon.isPlayer()) { return false; } - return this.activateTrap(pokemon); + return this.activateTrap(pokemon, simulated); } - activateTrap(pokemon: Pokemon): boolean { + activateTrap(pokemon: Pokemon, simulated: boolean): boolean { return false; } getMatchupScoreMultiplier(pokemon: Pokemon): number { return pokemon.isGrounded() ? 1 : Phaser.Math.Linear(0, 1 / Math.pow(2, this.layers), Math.min(pokemon.getHpRatio(), 0.5) * 2); } + + loadTag(source: any): void { + super.loadTag(source); + this.layers = source.layers; + this.maxLayers = source.maxLayers; + } } /** @@ -599,7 +654,7 @@ export class ArenaTrapTag extends ArenaTag { * in damage for 1, 2, or 3 layers of Spikes respectively if they are summoned into this trap. */ class SpikesTag extends ArenaTrapTag { - constructor(sourceId: integer, side: ArenaTagSide) { + constructor(sourceId: number, side: ArenaTagSide) { super(ArenaTagType.SPIKES, Moves.SPIKES, sourceId, side, 3); } @@ -612,14 +667,18 @@ class SpikesTag extends ArenaTrapTag { } } - activateTrap(pokemon: Pokemon): boolean { + override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { if (pokemon.isGrounded()) { - const cancelled = new Utils.BooleanHolder(false); + const cancelled = new BooleanHolder(false); applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); + if (simulated) { + return !cancelled.value; + } + if (!cancelled.value) { const damageHpRatio = 1 / (10 - 2 * this.layers); - const damage = Utils.toDmgValue(pokemon.getMaxHp() * damageHpRatio); + const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio); pokemon.scene.queueMessage(i18next.t("arenaTag:spikesActivateTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); pokemon.damageAndUpdate(damage, HitResult.OTHER); @@ -643,7 +702,7 @@ class SpikesTag extends ArenaTrapTag { class ToxicSpikesTag extends ArenaTrapTag { private neutralized: boolean; - constructor(sourceId: integer, side: ArenaTagSide) { + constructor(sourceId: number, side: ArenaTagSide) { super(ArenaTagType.TOXIC_SPIKES, Moves.TOXIC_SPIKES, sourceId, side, 2); this.neutralized = false; } @@ -663,8 +722,11 @@ class ToxicSpikesTag extends ArenaTrapTag { } } - activateTrap(pokemon: Pokemon): boolean { + override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { if (pokemon.isGrounded()) { + if (simulated) { + return true; + } if (pokemon.isOfType(Type.POISON)) { this.neutralized = true; if (pokemon.scene.arena.removeTag(this.tagType)) { @@ -701,7 +763,7 @@ class ToxicSpikesTag extends ArenaTrapTag { class DelayedAttackTag extends ArenaTag { public targetIndex: BattlerIndex; - constructor(tagType: ArenaTagType, sourceMove: Moves | undefined, sourceId: integer, targetIndex: BattlerIndex) { + constructor(tagType: ArenaTagType, sourceMove: Moves | undefined, sourceId: number, targetIndex: BattlerIndex) { super(tagType, 3, sourceMove, sourceId); this.targetIndex = targetIndex; @@ -726,7 +788,7 @@ class DelayedAttackTag extends ArenaTag { * who is summoned into the trap, based on the Rock type's type effectiveness. */ class StealthRockTag extends ArenaTrapTag { - constructor(sourceId: integer, side: ArenaTagSide) { + constructor(sourceId: number, side: ArenaTagSide) { super(ArenaTagType.STEALTH_ROCK, Moves.STEALTH_ROCK, sourceId, side, 1); } @@ -745,31 +807,31 @@ class StealthRockTag extends ArenaTrapTag { let damageHpRatio: number = 0; switch (effectiveness) { - case 0: - damageHpRatio = 0; - break; - case 0.25: - damageHpRatio = 0.03125; - break; - case 0.5: - damageHpRatio = 0.0625; - break; - case 1: - damageHpRatio = 0.125; - break; - case 2: - damageHpRatio = 0.25; - break; - case 4: - damageHpRatio = 0.5; - break; + case 0: + damageHpRatio = 0; + break; + case 0.25: + damageHpRatio = 0.03125; + break; + case 0.5: + damageHpRatio = 0.0625; + break; + case 1: + damageHpRatio = 0.125; + break; + case 2: + damageHpRatio = 0.25; + break; + case 4: + damageHpRatio = 0.5; + break; } return damageHpRatio; } - activateTrap(pokemon: Pokemon): boolean { - const cancelled = new Utils.BooleanHolder(false); + override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { + const cancelled = new BooleanHolder(false); applyAbAttrs(BlockNonDirectDamageAbAttr, pokemon, cancelled); if (cancelled.value) { @@ -779,12 +841,16 @@ class StealthRockTag extends ArenaTrapTag { const damageHpRatio = this.getDamageHpRatio(pokemon); if (damageHpRatio) { - const damage = Utils.toDmgValue(pokemon.getMaxHp() * damageHpRatio); + if (simulated) { + return true; + } + const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio); pokemon.scene.queueMessage(i18next.t("arenaTag:stealthRockActivateTrap", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); pokemon.damageAndUpdate(damage, HitResult.OTHER); if (pokemon.turnData) { pokemon.turnData.damageTaken += damage; } + return true; } return false; @@ -802,7 +868,7 @@ class StealthRockTag extends ArenaTrapTag { * to any Pokémon who is summoned into this trap. */ class StickyWebTag extends ArenaTrapTag { - constructor(sourceId: integer, side: ArenaTagSide) { + constructor(sourceId: number, side: ArenaTagSide) { super(ArenaTagType.STICKY_WEB, Moves.STICKY_WEB, sourceId, side, 1); } @@ -814,14 +880,20 @@ class StickyWebTag extends ArenaTrapTag { } } - activateTrap(pokemon: Pokemon): boolean { + override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { if (pokemon.isGrounded()) { - const cancelled = new Utils.BooleanHolder(false); + const cancelled = new BooleanHolder(false); applyAbAttrs(ProtectStatAbAttr, pokemon, cancelled); + + if (simulated) { + return !cancelled.value; + } + if (!cancelled.value) { pokemon.scene.queueMessage(i18next.t("arenaTag:stickyWebActivateTrap", { pokemonName: pokemon.getNameToRender() })); - const stages = new Utils.NumberHolder(-1); + const stages = new NumberHolder(-1); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), false, [ Stat.SPD ], stages.value)); + return true; } } @@ -836,12 +908,19 @@ class StickyWebTag extends ArenaTrapTag { * also reversing the turn order for all Pokémon on the field as well. */ export class TrickRoomTag extends ArenaTag { - constructor(turnCount: integer, sourceId: integer) { + constructor(turnCount: number, sourceId: number) { super(ArenaTagType.TRICK_ROOM, turnCount, Moves.TRICK_ROOM, sourceId); } - apply(arena: Arena, args: any[]): boolean { - const speedReversed = args[0] as Utils.BooleanHolder; + /** + * Reverses Speed-based turn order for all Pokemon on the field + * @param arena n/a + * @param simulated n/a + * @param speedReversed a {@linkcode BooleanHolder} used to flag if Speed-based + * turn order should be reversed. + * @returns `true` if turn order is successfully reversed; `false` otherwise + */ + override apply(arena: Arena, simulated: boolean, speedReversed: BooleanHolder): boolean { speedReversed.value = !speedReversed.value; return true; } @@ -864,7 +943,7 @@ export class TrickRoomTag extends ArenaTag { * {@linkcode Abilities.LEVITATE} for the duration of the arena tag, usually 5 turns. */ export class GravityTag extends ArenaTag { - constructor(turnCount: integer) { + constructor(turnCount: number) { super(ArenaTagType.GRAVITY, turnCount, Moves.GRAVITY); } @@ -872,7 +951,8 @@ export class GravityTag extends ArenaTag { arena.scene.queueMessage(i18next.t("arenaTag:gravityOnAdd")); arena.scene.getField(true).forEach((pokemon) => { if (pokemon !== null) { - pokemon.removeTag(BattlerTagType.MAGNET_RISEN); + pokemon.removeTag(BattlerTagType.FLOATING); + pokemon.removeTag(BattlerTagType.TELEKINESIS); } }); } @@ -888,7 +968,7 @@ export class GravityTag extends ArenaTag { * Applies this arena tag for 4 turns (including the turn the move was used). */ class TailwindTag extends ArenaTag { - constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { + constructor(turnCount: number, sourceId: number, side: ArenaTagSide) { super(ArenaTagType.TAILWIND, turnCount, Moves.TAILWIND, sourceId, side); } @@ -926,7 +1006,7 @@ class TailwindTag extends ArenaTag { * Doubles the prize money from trainers and money moves like {@linkcode Moves.PAY_DAY} and {@linkcode Moves.MAKE_IT_RAIN}. */ class HappyHourTag extends ArenaTag { - constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { + constructor(turnCount: number, sourceId: number, side: ArenaTagSide) { super(ArenaTagType.HAPPY_HOUR, turnCount, Moves.HAPPY_HOUR, sourceId, side); } @@ -940,7 +1020,7 @@ class HappyHourTag extends ArenaTag { } class SafeguardTag extends ArenaTag { - constructor(turnCount: integer, sourceId: integer, side: ArenaTagSide) { + constructor(turnCount: number, sourceId: number, side: ArenaTagSide) { super(ArenaTagType.SAFEGUARD, turnCount, Moves.SAFEGUARD, sourceId, side); } @@ -953,42 +1033,35 @@ class SafeguardTag extends ArenaTag { } } +class NoneTag extends ArenaTag { + constructor() { + super(ArenaTagType.NONE, 0); + } +} /** * This arena tag facilitates the application of the move Imprison * Imprison remains in effect as long as the source Pokemon is active and present on the field. * Imprison will apply to any opposing Pokemon that switch onto the field as well. */ class ImprisonTag extends ArenaTrapTag { - private source: Pokemon; - constructor(sourceId: number, side: ArenaTagSide) { super(ArenaTagType.IMPRISON, Moves.IMPRISON, sourceId, side, 1); } - /** - * Helper function that retrieves the Pokemon affected - * @param {BattleScene} scene medium to retrieve the involved Pokemon - * @returns list of PlayerPokemon or EnemyPokemon on the field - */ - private retrieveField(scene: BattleScene): PlayerPokemon[] | EnemyPokemon[] { - if (!this.source.isPlayer()) { - return scene.getPlayerField() ?? []; - } - return scene.getEnemyField() ?? []; - } - /** * This function applies the effects of Imprison to the opposing Pokemon already present on the field. * @param arena */ override onAdd({ scene }: Arena) { - this.source = scene.getPokemonById(this.sourceId!)!; - if (this.source) { - const party = this.retrieveField(scene); - party?.forEach((p: PlayerPokemon | EnemyPokemon ) => { - p.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId); + const source = this.getSourcePokemon(scene); + if (source) { + const party = this.getAffectedPokemon(scene); + party?.forEach((p: Pokemon ) => { + if (p.isAllowedInBattle()) { + p.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId); + } }); - scene.queueMessage(i18next.t("battlerTags:imprisonOnAdd", {pokemonNameWithAffix: getPokemonNameWithAffix(this.source)})); + scene.queueMessage(i18next.t("battlerTags:imprisonOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(source) })); } } @@ -997,8 +1070,9 @@ class ImprisonTag extends ArenaTrapTag { * @param _arena * @returns `true` if the source of the tag is still active on the field | `false` if not */ - override lapse(_arena: Arena): boolean { - return this.source.isActive(true); + override lapse({ scene }: Arena): boolean { + const source = this.getSourcePokemon(scene); + return source ? source.isActive(true) : false; } /** @@ -1007,7 +1081,8 @@ class ImprisonTag extends ArenaTrapTag { * @returns `true` */ override activateTrap(pokemon: Pokemon): boolean { - if (this.source.isActive(true)) { + const source = this.getSourcePokemon(pokemon.scene); + if (source && source.isActive(true) && pokemon.isAllowedInBattle()) { pokemon.addTag(BattlerTagType.IMPRISON, 1, Moves.IMPRISON, this.sourceId); } return true; @@ -1018,65 +1093,167 @@ class ImprisonTag extends ArenaTrapTag { * @param arena */ override onRemove({ scene }: Arena): void { - const party = this.retrieveField(scene); - party?.forEach((p: PlayerPokemon | EnemyPokemon) => { + const party = this.getAffectedPokemon(scene); + party?.forEach((p: Pokemon) => { p.removeTag(BattlerTagType.IMPRISON); }); } } -export function getArenaTag(tagType: ArenaTagType, turnCount: integer, sourceMove: Moves | undefined, sourceId: integer, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag | null { - switch (tagType) { - case ArenaTagType.MIST: - return new MistTag(turnCount, sourceId, side); - case ArenaTagType.QUICK_GUARD: - return new QuickGuardTag(sourceId, side); - case ArenaTagType.WIDE_GUARD: - return new WideGuardTag(sourceId, side); - case ArenaTagType.MAT_BLOCK: - return new MatBlockTag(sourceId, side); - case ArenaTagType.CRAFTY_SHIELD: - return new CraftyShieldTag(sourceId, side); - case ArenaTagType.NO_CRIT: - return new NoCritTag(turnCount, sourceMove!, sourceId, side); // TODO: is this bang correct? - case ArenaTagType.MUD_SPORT: - return new MudSportTag(turnCount, sourceId); - case ArenaTagType.WATER_SPORT: - return new WaterSportTag(turnCount, sourceId); - case ArenaTagType.PLASMA_FISTS: - return new PlasmaFistsTag(); - case ArenaTagType.SPIKES: - return new SpikesTag(sourceId, side); - case ArenaTagType.TOXIC_SPIKES: - return new ToxicSpikesTag(sourceId, side); - case ArenaTagType.FUTURE_SIGHT: - case ArenaTagType.DOOM_DESIRE: - return new DelayedAttackTag(tagType, sourceMove, sourceId, targetIndex!); // TODO:questionable bang - case ArenaTagType.WISH: - return new WishTag(turnCount, sourceId, side); - case ArenaTagType.STEALTH_ROCK: - return new StealthRockTag(sourceId, side); - case ArenaTagType.STICKY_WEB: - return new StickyWebTag(sourceId, side); - case ArenaTagType.TRICK_ROOM: - return new TrickRoomTag(turnCount, sourceId); - case ArenaTagType.GRAVITY: - return new GravityTag(turnCount); - case ArenaTagType.REFLECT: - return new ReflectTag(turnCount, sourceId, side); - case ArenaTagType.LIGHT_SCREEN: - return new LightScreenTag(turnCount, sourceId, side); - case ArenaTagType.AURORA_VEIL: - return new AuroraVeilTag(turnCount, sourceId, side); - case ArenaTagType.TAILWIND: - return new TailwindTag(turnCount, sourceId, side); - case ArenaTagType.HAPPY_HOUR: - return new HappyHourTag(turnCount, sourceId, side); - case ArenaTagType.SAFEGUARD: - return new SafeguardTag(turnCount, sourceId, side); - case ArenaTagType.IMPRISON: - return new ImprisonTag(sourceId, side); - default: - return null; +/** + * Arena Tag implementing the "sea of fire" effect from the combination + * of {@link https://bulbapedia.bulbagarden.net/wiki/Fire_Pledge_(move) | Fire Pledge} + * and {@link https://bulbapedia.bulbagarden.net/wiki/Grass_Pledge_(move) | Grass Pledge}. + * Damages all non-Fire-type Pokemon on the given side of the field at the end + * of each turn for 4 turns. + */ +class FireGrassPledgeTag extends ArenaTag { + constructor(sourceId: number, side: ArenaTagSide) { + super(ArenaTagType.FIRE_GRASS_PLEDGE, 4, Moves.FIRE_PLEDGE, sourceId, side); + } + + override onAdd(arena: Arena): void { + // "A sea of fire enveloped your/the opposing team!" + arena.scene.queueMessage(i18next.t(`arenaTag:fireGrassPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`)); + } + + override lapse(arena: Arena): boolean { + const field: Pokemon[] = (this.side === ArenaTagSide.PLAYER) + ? arena.scene.getPlayerField() + : arena.scene.getEnemyField(); + + field.filter(pokemon => !pokemon.isOfType(Type.FIRE)).forEach(pokemon => { + // "{pokemonNameWithAffix} was hurt by the sea of fire!" + pokemon.scene.queueMessage(i18next.t("arenaTag:fireGrassPledgeLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); + // TODO: Replace this with a proper animation + pokemon.scene.unshiftPhase(new CommonAnimPhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.getBattlerIndex(), CommonAnim.MAGMA_STORM)); + pokemon.damageAndUpdate(toDmgValue(pokemon.getMaxHp() / 8)); + }); + + return super.lapse(arena); } } + +/** + * Arena Tag implementing the "rainbow" effect from the combination + * of {@link https://bulbapedia.bulbagarden.net/wiki/Water_Pledge_(move) | Water Pledge} + * and {@link https://bulbapedia.bulbagarden.net/wiki/Fire_Pledge_(move) | Fire Pledge}. + * Doubles the secondary effect chance of moves from Pokemon on the + * given side of the field for 4 turns. + */ +class WaterFirePledgeTag extends ArenaTag { + constructor(sourceId: number, side: ArenaTagSide) { + super(ArenaTagType.WATER_FIRE_PLEDGE, 4, Moves.WATER_PLEDGE, sourceId, side); + } + + override onAdd(arena: Arena): void { + // "A rainbow appeared in the sky on your/the opposing team's side!" + arena.scene.queueMessage(i18next.t(`arenaTag:waterFirePledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`)); + } + + /** + * Doubles the chance for the given move's secondary effect(s) to trigger + * @param arena the {@linkcode Arena} containing this tag + * @param simulated n/a + * @param moveChance a {@linkcode NumberHolder} containing + * the move's current effect chance + * @returns `true` if the move's effect chance was doubled (currently always `true`) + */ + override apply(arena: Arena, simulated: boolean, moveChance: NumberHolder): boolean { + moveChance.value *= 2; + return true; + } +} + +/** + * Arena Tag implementing the "swamp" effect from the combination + * of {@link https://bulbapedia.bulbagarden.net/wiki/Grass_Pledge_(move) | Grass Pledge} + * and {@link https://bulbapedia.bulbagarden.net/wiki/Water_Pledge_(move) | Water Pledge}. + * Quarters the Speed of Pokemon on the given side of the field for 4 turns. + */ +class GrassWaterPledgeTag extends ArenaTag { + constructor(sourceId: number, side: ArenaTagSide) { + super(ArenaTagType.GRASS_WATER_PLEDGE, 4, Moves.GRASS_PLEDGE, sourceId, side); + } + + override onAdd(arena: Arena): void { + // "A swamp enveloped your/the opposing team!" + arena.scene.queueMessage(i18next.t(`arenaTag:grassWaterPledgeOnAdd${this.side === ArenaTagSide.PLAYER ? "Player" : this.side === ArenaTagSide.ENEMY ? "Enemy" : ""}`)); + } +} + +// TODO: swap `sourceMove` and `sourceId` and make `sourceMove` an optional parameter +export function getArenaTag(tagType: ArenaTagType, turnCount: number, sourceMove: Moves | undefined, sourceId: number, targetIndex?: BattlerIndex, side: ArenaTagSide = ArenaTagSide.BOTH): ArenaTag | null { + switch (tagType) { + case ArenaTagType.MIST: + return new MistTag(turnCount, sourceId, side); + case ArenaTagType.QUICK_GUARD: + return new QuickGuardTag(sourceId, side); + case ArenaTagType.WIDE_GUARD: + return new WideGuardTag(sourceId, side); + case ArenaTagType.MAT_BLOCK: + return new MatBlockTag(sourceId, side); + case ArenaTagType.CRAFTY_SHIELD: + return new CraftyShieldTag(sourceId, side); + case ArenaTagType.NO_CRIT: + return new NoCritTag(turnCount, sourceMove!, sourceId, side); // TODO: is this bang correct? + case ArenaTagType.MUD_SPORT: + return new MudSportTag(turnCount, sourceId); + case ArenaTagType.WATER_SPORT: + return new WaterSportTag(turnCount, sourceId); + case ArenaTagType.ION_DELUGE: + return new IonDelugeTag(sourceMove); + case ArenaTagType.SPIKES: + return new SpikesTag(sourceId, side); + case ArenaTagType.TOXIC_SPIKES: + return new ToxicSpikesTag(sourceId, side); + case ArenaTagType.FUTURE_SIGHT: + case ArenaTagType.DOOM_DESIRE: + return new DelayedAttackTag(tagType, sourceMove, sourceId, targetIndex!); // TODO:questionable bang + case ArenaTagType.WISH: + return new WishTag(turnCount, sourceId, side); + case ArenaTagType.STEALTH_ROCK: + return new StealthRockTag(sourceId, side); + case ArenaTagType.STICKY_WEB: + return new StickyWebTag(sourceId, side); + case ArenaTagType.TRICK_ROOM: + return new TrickRoomTag(turnCount, sourceId); + case ArenaTagType.GRAVITY: + return new GravityTag(turnCount); + case ArenaTagType.REFLECT: + return new ReflectTag(turnCount, sourceId, side); + case ArenaTagType.LIGHT_SCREEN: + return new LightScreenTag(turnCount, sourceId, side); + case ArenaTagType.AURORA_VEIL: + return new AuroraVeilTag(turnCount, sourceId, side); + case ArenaTagType.TAILWIND: + return new TailwindTag(turnCount, sourceId, side); + case ArenaTagType.HAPPY_HOUR: + return new HappyHourTag(turnCount, sourceId, side); + case ArenaTagType.SAFEGUARD: + return new SafeguardTag(turnCount, sourceId, side); + case ArenaTagType.IMPRISON: + return new ImprisonTag(sourceId, side); + case ArenaTagType.FIRE_GRASS_PLEDGE: + return new FireGrassPledgeTag(sourceId, side); + case ArenaTagType.WATER_FIRE_PLEDGE: + return new WaterFirePledgeTag(sourceId, side); + case ArenaTagType.GRASS_WATER_PLEDGE: + return new GrassWaterPledgeTag(sourceId, side); + default: + return null; + } +} + +/** + * When given a battler tag or json representing one, creates an actual ArenaTag object with the same data. + * @param {ArenaTag | any} source An arena tag + * @return {ArenaTag} The valid arena tag + */ +export function loadArenaTag(source: ArenaTag | any): ArenaTag { + const tag = getArenaTag(source.tagType, source.turnCount, source.sourceMove, source.sourceId, source.targetIndex, source.side) + ?? new NoneTag(); + tag.loadTag(source); + return tag; +} + diff --git a/src/data/balance/biomes.ts b/src/data/balance/biomes.ts index f35bd56b3a4..2ce693c360b 100644 --- a/src/data/balance/biomes.ts +++ b/src/data/balance/biomes.ts @@ -13,14 +13,14 @@ export function getBiomeName(biome: Biome | -1) { return i18next.t("biome:unknownLocation"); } switch (biome) { - case Biome.GRASS: - return i18next.t("biome:GRASS"); - case Biome.RUINS: - return i18next.t("biome:RUINS"); - case Biome.END: - return i18next.t("biome:END"); - default: - return i18next.t(`biome:${Biome[biome].toUpperCase()}`); + case Biome.GRASS: + return i18next.t("biome:GRASS"); + case Biome.RUINS: + return i18next.t("biome:RUINS"); + case Biome.END: + return i18next.t("biome:END"); + default: + return i18next.t(`biome:${Biome[biome].toUpperCase()}`); } } @@ -37,34 +37,34 @@ export const biomeLinks: BiomeLinks = { [Biome.PLAINS]: [ Biome.GRASS, Biome.METROPOLIS, Biome.LAKE ], [Biome.GRASS]: Biome.TALL_GRASS, [Biome.TALL_GRASS]: [ Biome.FOREST, Biome.CAVE ], - [Biome.SLUM]: [ Biome.CONSTRUCTION_SITE, [ Biome.SWAMP, 2 ] ], + [Biome.SLUM]: [ Biome.CONSTRUCTION_SITE, [ Biome.SWAMP, 2 ]], [Biome.FOREST]: [ Biome.JUNGLE, Biome.MEADOW ], [Biome.SEA]: [ Biome.SEABED, Biome.ICE_CAVE ], [Biome.SWAMP]: [ Biome.GRAVEYARD, Biome.TALL_GRASS ], - [Biome.BEACH]: [ Biome.SEA, [ Biome.ISLAND, 2 ] ], + [Biome.BEACH]: [ Biome.SEA, [ Biome.ISLAND, 2 ]], [Biome.LAKE]: [ Biome.BEACH, Biome.SWAMP, Biome.CONSTRUCTION_SITE ], - [Biome.SEABED]: [ Biome.CAVE, [ Biome.VOLCANO, 3 ] ], - [Biome.MOUNTAIN]: [ Biome.VOLCANO, [ Biome.WASTELAND, 2 ], [ Biome.SPACE, 3 ] ], + [Biome.SEABED]: [ Biome.CAVE, [ Biome.VOLCANO, 3 ]], + [Biome.MOUNTAIN]: [ Biome.VOLCANO, [ Biome.WASTELAND, 2 ], [ Biome.SPACE, 3 ]], [Biome.BADLANDS]: [ Biome.DESERT, Biome.MOUNTAIN ], - [Biome.CAVE]: [ Biome.BADLANDS, Biome.LAKE, [ Biome.LABORATORY, 2 ] ], - [Biome.DESERT]: [ Biome.RUINS, [ Biome.CONSTRUCTION_SITE, 2 ] ], + [Biome.CAVE]: [ Biome.BADLANDS, Biome.LAKE, [ Biome.LABORATORY, 2 ]], + [Biome.DESERT]: [ Biome.RUINS, [ Biome.CONSTRUCTION_SITE, 2 ]], [Biome.ICE_CAVE]: Biome.SNOWY_FOREST, [Biome.MEADOW]: [ Biome.PLAINS, Biome.FAIRY_CAVE ], [Biome.POWER_PLANT]: Biome.FACTORY, - [Biome.VOLCANO]: [ Biome.BEACH, [ Biome.ICE_CAVE, 3 ] ], + [Biome.VOLCANO]: [ Biome.BEACH, [ Biome.ICE_CAVE, 3 ]], [Biome.GRAVEYARD]: Biome.ABYSS, - [Biome.DOJO]: [ Biome.PLAINS, [ Biome.JUNGLE, 2], [ Biome.TEMPLE, 2 ] ], - [Biome.FACTORY]: [ Biome.PLAINS, [ Biome.LABORATORY, 2 ] ], - [Biome.RUINS]: [ Biome.MOUNTAIN, [ Biome.FOREST, 2 ] ], + [Biome.DOJO]: [ Biome.PLAINS, [ Biome.JUNGLE, 2 ], [ Biome.TEMPLE, 2 ]], + [Biome.FACTORY]: [ Biome.PLAINS, [ Biome.LABORATORY, 2 ]], + [Biome.RUINS]: [ Biome.MOUNTAIN, [ Biome.FOREST, 2 ]], [Biome.WASTELAND]: Biome.BADLANDS, - [Biome.ABYSS]: [ Biome.CAVE, [ Biome.SPACE, 2 ], [ Biome.WASTELAND, 2 ] ], + [Biome.ABYSS]: [ Biome.CAVE, [ Biome.SPACE, 2 ], [ Biome.WASTELAND, 2 ]], [Biome.SPACE]: Biome.RUINS, - [Biome.CONSTRUCTION_SITE]: [ Biome.POWER_PLANT, [ Biome.DOJO, 2 ] ], + [Biome.CONSTRUCTION_SITE]: [ Biome.POWER_PLANT, [ Biome.DOJO, 2 ]], [Biome.JUNGLE]: [ Biome.TEMPLE ], - [Biome.FAIRY_CAVE]: [ Biome.ICE_CAVE, [ Biome.SPACE, 2 ] ], - [Biome.TEMPLE]: [ Biome.DESERT, [ Biome.SWAMP, 2 ], [ Biome.RUINS, 2 ] ], + [Biome.FAIRY_CAVE]: [ Biome.ICE_CAVE, [ Biome.SPACE, 2 ]], + [Biome.TEMPLE]: [ Biome.DESERT, [ Biome.SWAMP, 2 ], [ Biome.RUINS, 2 ]], [Biome.METROPOLIS]: Biome.SLUM, - [Biome.SNOWY_FOREST]: [ Biome.FOREST, [ Biome.MOUNTAIN, 2 ], [ Biome.LAKE, 2 ] ], + [Biome.SNOWY_FOREST]: [ Biome.FOREST, [ Biome.MOUNTAIN, 2 ], [ Biome.LAKE, 2 ]], [Biome.ISLAND]: Biome.SEA, [Biome.LABORATORY]: Biome.CONSTRUCTION_SITE }; @@ -113,7 +113,7 @@ export const biomePokemonPools: BiomePokemonPools = { [Biome.TOWN]: { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [ - { 1: [ Species.CATERPIE ], 7: [ Species.METAPOD ] }, + { 1: [ Species.CATERPIE ], 7: [ Species.METAPOD ]}, Species.SENTRET, Species.LEDYBA, Species.HOPPIP, @@ -121,12 +121,12 @@ export const biomePokemonPools: BiomePokemonPools = { Species.STARLY, Species.PIDOVE, Species.COTTONEE, - { 1: [ Species.SCATTERBUG ], 9: [ Species.SPEWPA ] }, + { 1: [ Species.SCATTERBUG ], 9: [ Species.SPEWPA ]}, Species.YUNGOOS, Species.SKWOVET ], [TimeOfDay.DAY]: [ - { 1: [ Species.CATERPIE ], 7: [ Species.METAPOD ] }, + { 1: [ Species.CATERPIE ], 7: [ Species.METAPOD ]}, Species.SENTRET, Species.HOPPIP, Species.SUNKERN, @@ -134,12 +134,12 @@ export const biomePokemonPools: BiomePokemonPools = { Species.STARLY, Species.PIDOVE, Species.COTTONEE, - { 1: [ Species.SCATTERBUG ], 9: [ Species.SPEWPA ] }, + { 1: [ Species.SCATTERBUG ], 9: [ Species.SPEWPA ]}, Species.YUNGOOS, Species.SKWOVET ], - [TimeOfDay.DUSK]: [ { 1: [ Species.WEEDLE ], 7: [ Species.KAKUNA ] }, Species.POOCHYENA, Species.PATRAT, Species.PURRLOIN, Species.BLIPBUG ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.WEEDLE ], 7: [ Species.KAKUNA ] }, Species.HOOTHOOT, Species.SPINARAK, Species.POOCHYENA, Species.CASCOON, Species.PATRAT, Species.PURRLOIN, Species.BLIPBUG ], + [TimeOfDay.DUSK]: [{ 1: [ Species.WEEDLE ], 7: [ Species.KAKUNA ]}, Species.POOCHYENA, Species.PATRAT, Species.PURRLOIN, Species.BLIPBUG ], + [TimeOfDay.NIGHT]: [{ 1: [ Species.WEEDLE ], 7: [ Species.KAKUNA ]}, Species.HOOTHOOT, Species.SPINARAK, Species.POOCHYENA, Species.CASCOON, Species.PATRAT, Species.PURRLOIN, Species.BLIPBUG ], [TimeOfDay.ALL]: [ Species.PIDGEY, Species.RATTATA, Species.SPEAROW, Species.ZIGZAGOON, Species.WURMPLE, Species.TAILLOW, Species.BIDOOF, Species.LILLIPUP, Species.FLETCHLING, Species.WOOLOO, Species.LECHONK ] }, [BiomePoolTier.UNCOMMON]: { @@ -149,56 +149,56 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.EKANS, Species.ODDISH, Species.PARAS, Species.VENONAT, Species.MEOWTH, Species.SEEDOT, Species.SHROOMISH, Species.KRICKETOT, Species.VENIPEDE ], [TimeOfDay.ALL]: [ Species.NINCADA, Species.WHISMUR, Species.FIDOUGH ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [ Species.TANDEMAUS ], [TimeOfDay.DAY]: [ Species.TANDEMAUS ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ABRA, Species.SURSKIT, Species.ROOKIDEE ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.EEVEE, Species.RALTS ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DITTO ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [ Species.TANDEMAUS ], [TimeOfDay.DAY]: [ Species.TANDEMAUS ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ABRA, Species.SURSKIT, Species.ROOKIDEE ]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.EEVEE, Species.RALTS ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DITTO ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.PLAINS]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.SENTRET ], 15: [ Species.FURRET ] }, { 1: [ Species.YUNGOOS ], 30: [ Species.GUMSHOOS ] }, { 1: [ Species.SKWOVET ], 24: [ Species.GREEDENT ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.SENTRET ], 15: [ Species.FURRET ] }, { 1: [ Species.YUNGOOS ], 30: [ Species.GUMSHOOS ] }, { 1: [ Species.SKWOVET ], 24: [ Species.GREEDENT ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.MEOWTH ], 28: [ Species.PERSIAN ] }, { 1: [ Species.POOCHYENA ], 18: [ Species.MIGHTYENA ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.ZUBAT ], 22: [ Species.GOLBAT ] }, { 1: [ Species.MEOWTH ], 28: [ Species.PERSIAN ] }, { 1: [ Species.POOCHYENA ], 18: [ Species.MIGHTYENA ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.ZIGZAGOON ], 20: [ Species.LINOONE ] }, { 1: [ Species.BIDOOF ], 15: [ Species.BIBAREL ] }, { 1: [ Species.LECHONK ], 18: [ Species.OINKOLOGNE ] } ] + [TimeOfDay.DAWN]: [{ 1: [ Species.SENTRET ], 15: [ Species.FURRET ]}, { 1: [ Species.YUNGOOS ], 30: [ Species.GUMSHOOS ]}, { 1: [ Species.SKWOVET ], 24: [ Species.GREEDENT ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.SENTRET ], 15: [ Species.FURRET ]}, { 1: [ Species.YUNGOOS ], 30: [ Species.GUMSHOOS ]}, { 1: [ Species.SKWOVET ], 24: [ Species.GREEDENT ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.MEOWTH ], 28: [ Species.PERSIAN ]}, { 1: [ Species.POOCHYENA ], 18: [ Species.MIGHTYENA ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.ZUBAT ], 22: [ Species.GOLBAT ]}, { 1: [ Species.MEOWTH ], 28: [ Species.PERSIAN ]}, { 1: [ Species.POOCHYENA ], 18: [ Species.MIGHTYENA ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.ZIGZAGOON ], 20: [ Species.LINOONE ]}, { 1: [ Species.BIDOOF ], 15: [ Species.BIBAREL ]}, { 1: [ Species.LECHONK ], 18: [ Species.OINKOLOGNE ]}] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [ - { 1: [ Species.DODUO ], 31: [ Species.DODRIO ] }, - { 1: [ Species.POOCHYENA ], 18: [ Species.MIGHTYENA ] }, - { 1: [ Species.STARLY ], 14: [ Species.STARAVIA ], 34: [ Species.STARAPTOR ] }, - { 1: [ Species.PIDOVE ], 21: [ Species.TRANQUILL ], 32: [ Species.UNFEZANT ] }, - { 1: [ Species.PAWMI ], 18: [ Species.PAWMO ], 32: [ Species.PAWMOT ] } + { 1: [ Species.DODUO ], 31: [ Species.DODRIO ]}, + { 1: [ Species.POOCHYENA ], 18: [ Species.MIGHTYENA ]}, + { 1: [ Species.STARLY ], 14: [ Species.STARAVIA ], 34: [ Species.STARAPTOR ]}, + { 1: [ Species.PIDOVE ], 21: [ Species.TRANQUILL ], 32: [ Species.UNFEZANT ]}, + { 1: [ Species.PAWMI ], 18: [ Species.PAWMO ], 32: [ Species.PAWMOT ]} ], [TimeOfDay.DAY]: [ - { 1: [ Species.DODUO ], 31: [ Species.DODRIO ] }, - { 1: [ Species.POOCHYENA ], 18: [ Species.MIGHTYENA ] }, - { 1: [ Species.STARLY ], 14: [ Species.STARAVIA ], 34: [ Species.STARAPTOR ] }, - { 1: [ Species.PIDOVE ], 21: [ Species.TRANQUILL ], 32: [ Species.UNFEZANT ] }, - { 1: [ Species.ROCKRUFF ], 25: [ Species.LYCANROC ] }, - { 1: [ Species.PAWMI ], 18: [ Species.PAWMO ], 32: [ Species.PAWMOT ] } + { 1: [ Species.DODUO ], 31: [ Species.DODRIO ]}, + { 1: [ Species.POOCHYENA ], 18: [ Species.MIGHTYENA ]}, + { 1: [ Species.STARLY ], 14: [ Species.STARAVIA ], 34: [ Species.STARAPTOR ]}, + { 1: [ Species.PIDOVE ], 21: [ Species.TRANQUILL ], 32: [ Species.UNFEZANT ]}, + { 1: [ Species.ROCKRUFF ], 25: [ Species.LYCANROC ]}, + { 1: [ Species.PAWMI ], 18: [ Species.PAWMO ], 32: [ Species.PAWMOT ]} ], - [TimeOfDay.DUSK]: [ { 1: [ Species.MANKEY ], 28: [ Species.PRIMEAPE ], 75: [ Species.ANNIHILAPE ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.MANKEY ], 28: [ Species.PRIMEAPE ], 75: [ Species.ANNIHILAPE ] } ], + [TimeOfDay.DUSK]: [{ 1: [ Species.MANKEY ], 28: [ Species.PRIMEAPE ], 75: [ Species.ANNIHILAPE ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.MANKEY ], 28: [ Species.PRIMEAPE ], 75: [ Species.ANNIHILAPE ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.PIDGEY ], 18: [ Species.PIDGEOTTO ], 36: [ Species.PIDGEOT ] }, - { 1: [ Species.SPEAROW ], 20: [ Species.FEAROW ] }, + { 1: [ Species.PIDGEY ], 18: [ Species.PIDGEOTTO ], 36: [ Species.PIDGEOT ]}, + { 1: [ Species.SPEAROW ], 20: [ Species.FEAROW ]}, Species.PIKACHU, - { 1: [ Species.FLETCHLING ], 17: [ Species.FLETCHINDER ], 35: [ Species.TALONFLAME ] } + { 1: [ Species.FLETCHLING ], 17: [ Species.FLETCHINDER ], 35: [ Species.TALONFLAME ]} ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [ Species.PALDEA_TAUROS ], [TimeOfDay.DAY]: [ Species.PALDEA_TAUROS ], - [TimeOfDay.DUSK]: [ { 1: [ Species.SHINX ], 15: [ Species.LUXIO ], 30: [ Species.LUXRAY ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.SHINX ], 15: [ Species.LUXIO ], 30: [ Species.LUXRAY ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.ABRA ], 16: [ Species.KADABRA ] }, { 1: [ Species.BUNEARY ], 20: [ Species.LOPUNNY ] }, { 1: [ Species.ROOKIDEE ], 18: [ Species.CORVISQUIRE ], 38: [ Species.CORVIKNIGHT ] } ] + [TimeOfDay.DUSK]: [{ 1: [ Species.SHINX ], 15: [ Species.LUXIO ], 30: [ Species.LUXRAY ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.SHINX ], 15: [ Species.LUXIO ], 30: [ Species.LUXRAY ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.ABRA ], 16: [ Species.KADABRA ]}, { 1: [ Species.BUNEARY ], 20: [ Species.LOPUNNY ]}, { 1: [ Species.ROOKIDEE ], 18: [ Species.CORVISQUIRE ], 38: [ Species.CORVIKNIGHT ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.FARFETCHD, Species.LICKITUNG, Species.CHANSEY, Species.EEVEE, Species.SNORLAX, { 1: [ Species.DUNSPARCE ], 62: [ Species.DUDUNSPARCE ] } ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DITTO, Species.LATIAS, Species.LATIOS ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.FARFETCHD, Species.LICKITUNG, Species.CHANSEY, Species.EEVEE, Species.SNORLAX, { 1: [ Species.DUNSPARCE ], 62: [ Species.DUDUNSPARCE ]}]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DITTO, Species.LATIAS, Species.LATIOS ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.DODRIO, Species.FURRET, Species.GUMSHOOS, Species.GREEDENT ], [TimeOfDay.DAY]: [ Species.DODRIO, Species.FURRET, Species.GUMSHOOS, Species.GREEDENT ], @@ -213,22 +213,22 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.FARFETCHD, Species.SNORLAX, Species.LICKILICKY, Species.DUDUNSPARCE ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.LATIAS, Species.LATIOS ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.LATIAS, Species.LATIOS ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.GRASS]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.HOPPIP ], 18: [ Species.SKIPLOOM ] }, Species.SUNKERN, Species.COTTONEE, Species.PETILIL ], - [TimeOfDay.DAY]: [ { 1: [ Species.HOPPIP ], 18: [ Species.SKIPLOOM ] }, Species.SUNKERN, Species.COTTONEE, Species.PETILIL ], - [TimeOfDay.DUSK]: [ { 1: [ Species.SEEDOT ], 14: [ Species.NUZLEAF ] }, { 1: [ Species.SHROOMISH ], 23: [ Species.BRELOOM ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.SEEDOT ], 14: [ Species.NUZLEAF ] }, { 1: [ Species.SHROOMISH ], 23: [ Species.BRELOOM ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.HOPPIP ], 18: [ Species.SKIPLOOM ]}, Species.SUNKERN, Species.COTTONEE, Species.PETILIL ], + [TimeOfDay.DAY]: [{ 1: [ Species.HOPPIP ], 18: [ Species.SKIPLOOM ]}, Species.SUNKERN, Species.COTTONEE, Species.PETILIL ], + [TimeOfDay.DUSK]: [{ 1: [ Species.SEEDOT ], 14: [ Species.NUZLEAF ]}, { 1: [ Species.SHROOMISH ], 23: [ Species.BRELOOM ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.SEEDOT ], 14: [ Species.NUZLEAF ]}, { 1: [ Species.SHROOMISH ], 23: [ Species.BRELOOM ]}], [TimeOfDay.ALL]: [] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.COMBEE ], 21: [ Species.VESPIQUEN ] }, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.COMBEE ], 21: [ Species.VESPIQUEN ] }, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.COMBEE ], 21: [ Species.VESPIQUEN ]}, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.COMBEE ], 21: [ Species.VESPIQUEN ]}, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ]}], [TimeOfDay.ALL]: [] }, [BiomePoolTier.RARE]: { @@ -236,28 +236,28 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ { 1: [ Species.BULBASAUR ], 16: [ Species.IVYSAUR ], 32: [ Species.VENUSAUR ] }, Species.GROWLITHE, { 1: [ Species.TURTWIG ], 18: [ Species.GROTLE ], 32: [ Species.TORTERRA ] } ] + [TimeOfDay.ALL]: [{ 1: [ Species.BULBASAUR ], 16: [ Species.IVYSAUR ], 32: [ Species.VENUSAUR ]}, Species.GROWLITHE, { 1: [ Species.TURTWIG ], 18: [ Species.GROTLE ], 32: [ Species.TORTERRA ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SUDOWOODO ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.VIRIZION ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.JUMPLUFF, Species.SUNFLORA, Species.WHIMSICOTT ], [TimeOfDay.DAY]: [ Species.JUMPLUFF, Species.SUNFLORA, Species.WHIMSICOTT ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.VENUSAUR, Species.SUDOWOODO, Species.TORTERRA ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.VIRIZION ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SUDOWOODO ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.VIRIZION ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.JUMPLUFF, Species.SUNFLORA, Species.WHIMSICOTT ], [TimeOfDay.DAY]: [ Species.JUMPLUFF, Species.SUNFLORA, Species.WHIMSICOTT ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.VENUSAUR, Species.SUDOWOODO, Species.TORTERRA ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.VIRIZION ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.TALL_GRASS]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.BOUNSWEET ], 18: [ Species.STEENEE ], 58: [ Species.TSAREENA ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.NIDORAN_F ], 16: [ Species.NIDORINA ] }, { 1: [ Species.NIDORAN_M ], 16: [ Species.NIDORINO ] }, { 1: [ Species.BOUNSWEET ], 18: [ Species.STEENEE ], 58: [ Species.TSAREENA ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.ODDISH ], 21: [ Species.GLOOM ] }, { 1: [ Species.KRICKETOT ], 10: [ Species.KRICKETUNE ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.ODDISH ], 21: [ Species.GLOOM ] }, { 1: [ Species.KRICKETOT ], 10: [ Species.KRICKETUNE ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.NINCADA ], 20: [ Species.NINJASK ] }, { 1: [ Species.FOMANTIS ], 44: [ Species.LURANTIS ] }, { 1: [ Species.NYMBLE ], 24: [ Species.LOKIX ] } ] + [TimeOfDay.DAWN]: [{ 1: [ Species.BOUNSWEET ], 18: [ Species.STEENEE ], 58: [ Species.TSAREENA ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.NIDORAN_F ], 16: [ Species.NIDORINA ]}, { 1: [ Species.NIDORAN_M ], 16: [ Species.NIDORINO ]}, { 1: [ Species.BOUNSWEET ], 18: [ Species.STEENEE ], 58: [ Species.TSAREENA ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.ODDISH ], 21: [ Species.GLOOM ]}, { 1: [ Species.KRICKETOT ], 10: [ Species.KRICKETUNE ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.ODDISH ], 21: [ Species.GLOOM ]}, { 1: [ Species.KRICKETOT ], 10: [ Species.KRICKETUNE ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.NINCADA ], 20: [ Species.NINJASK ]}, { 1: [ Species.FOMANTIS ], 44: [ Species.LURANTIS ]}, { 1: [ Species.NYMBLE ], 24: [ Species.LOKIX ]}] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], - [TimeOfDay.NIGHT]: [ { 1: [ Species.PARAS ], 24: [ Species.PARASECT ] }, { 1: [ Species.VENONAT ], 31: [ Species.VENOMOTH ] }, { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ] } ], + [TimeOfDay.NIGHT]: [{ 1: [ Species.PARAS ], 24: [ Species.PARASECT ]}, { 1: [ Species.VENONAT ], 31: [ Species.VENOMOTH ]}, { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ]}], [TimeOfDay.ALL]: [ Species.VULPIX ] }, [BiomePoolTier.RARE]: { @@ -265,10 +265,10 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ Species.PINSIR, { 1: [ Species.CHIKORITA ], 16: [ Species.BAYLEEF ], 32: [ Species.MEGANIUM ] }, { 1: [ Species.GIRAFARIG ], 62: [ Species.FARIGIRAF ] }, Species.ZANGOOSE, Species.KECLEON, Species.TROPIUS ] + [TimeOfDay.ALL]: [ Species.PINSIR, { 1: [ Species.CHIKORITA ], 16: [ Species.BAYLEEF ], 32: [ Species.MEGANIUM ]}, { 1: [ Species.GIRAFARIG ], 62: [ Species.FARIGIRAF ]}, Species.ZANGOOSE, Species.KECLEON, Species.TROPIUS ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SCYTHER, Species.SHEDINJA, Species.ROTOM ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SCYTHER, Species.SHEDINJA, Species.ROTOM ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.TSAREENA ], [TimeOfDay.DAY]: [ Species.NIDOQUEEN, Species.NIDOKING, Species.TSAREENA ], @@ -276,87 +276,87 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.VILEPLUME, Species.KRICKETUNE ], [TimeOfDay.ALL]: [ Species.NINJASK, Species.ZANGOOSE, Species.KECLEON, Species.LURANTIS, Species.LOKIX ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ Species.BELLOSSOM ], [TimeOfDay.DAY]: [ Species.BELLOSSOM ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.PINSIR, Species.MEGANIUM, Species.FARIGIRAF ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROTOM ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ Species.BELLOSSOM ], [TimeOfDay.DAY]: [ Species.BELLOSSOM ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.PINSIR, Species.MEGANIUM, Species.FARIGIRAF ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROTOM ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.METROPOLIS]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.YAMPER ], 25: [ Species.BOLTUND ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.YAMPER ], 25: [ Species.BOLTUND ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.HOUNDOUR ], 24: [ Species.HOUNDOOM ] }, { 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.RATTATA ], 20: [ Species.RATICATE ] }, { 1: [ Species.ZIGZAGOON ], 20: [ Species.LINOONE ] }, { 1: [ Species.LILLIPUP ], 16: [ Species.HERDIER ], 32: [ Species.STOUTLAND ] } ] + [TimeOfDay.DAWN]: [{ 1: [ Species.YAMPER ], 25: [ Species.BOLTUND ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.YAMPER ], 25: [ Species.BOLTUND ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.HOUNDOUR ], 24: [ Species.HOUNDOOM ]}, { 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.RATTATA ], 20: [ Species.RATICATE ]}, { 1: [ Species.ZIGZAGOON ], 20: [ Species.LINOONE ]}, { 1: [ Species.LILLIPUP ], 16: [ Species.HERDIER ], 32: [ Species.STOUTLAND ]}] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ] }, Species.INDEEDEE ], - [TimeOfDay.DAY]: [ { 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ] }, Species.INDEEDEE ], - [TimeOfDay.DUSK]: [ { 1: [ Species.ESPURR ], 25: [ Species.MEOWSTIC ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.ESPURR ], 25: [ Species.MEOWSTIC ] } ], - [TimeOfDay.ALL]: [ Species.PIKACHU, { 1: [ Species.GLAMEOW ], 38: [ Species.PURUGLY ] }, Species.FURFROU, { 1: [ Species.FIDOUGH ], 26: [ Species.DACHSBUN ] }, Species.SQUAWKABILLY ] + [TimeOfDay.DAWN]: [{ 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ]}, Species.INDEEDEE ], + [TimeOfDay.DAY]: [{ 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ]}, Species.INDEEDEE ], + [TimeOfDay.DUSK]: [{ 1: [ Species.ESPURR ], 25: [ Species.MEOWSTIC ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.ESPURR ], 25: [ Species.MEOWSTIC ]}], + [TimeOfDay.ALL]: [ Species.PIKACHU, { 1: [ Species.GLAMEOW ], 38: [ Species.PURUGLY ]}, Species.FURFROU, { 1: [ Species.FIDOUGH ], 26: [ Species.DACHSBUN ]}, Species.SQUAWKABILLY ] }, [BiomePoolTier.RARE]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.TANDEMAUS ], 25: [ Species.MAUSHOLD ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.TANDEMAUS ], 25: [ Species.MAUSHOLD ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.TANDEMAUS ], 25: [ Species.MAUSHOLD ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.TANDEMAUS ], 25: [ Species.MAUSHOLD ]}], [TimeOfDay.DUSK]: [ Species.MORPEKO ], [TimeOfDay.NIGHT]: [ Species.MORPEKO ], - [TimeOfDay.ALL]: [ { 1: [ Species.VAROOM ], 40: [ Species.REVAVROOM ] } ] + [TimeOfDay.ALL]: [{ 1: [ Species.VAROOM ], 40: [ Species.REVAVROOM ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DITTO, Species.EEVEE, Species.SMEARGLE ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CASTFORM ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.BOLTUND ], [TimeOfDay.DAY]: [ Species.BOLTUND ], [TimeOfDay.DUSK]: [ Species.MEOWSTIC ], [TimeOfDay.NIGHT]: [ Species.MEOWSTIC ], [TimeOfDay.ALL]: [ Species.STOUTLAND, Species.FURFROU, Species.DACHSBUN ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ Species.MAUSHOLD ], [TimeOfDay.DAY]: [ Species.MAUSHOLD ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CASTFORM, Species.REVAVROOM ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DITTO, Species.EEVEE, Species.SMEARGLE ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CASTFORM ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.BOLTUND ], [TimeOfDay.DAY]: [ Species.BOLTUND ], [TimeOfDay.DUSK]: [ Species.MEOWSTIC ], [TimeOfDay.NIGHT]: [ Species.MEOWSTIC ], [TimeOfDay.ALL]: [ Species.STOUTLAND, Species.FURFROU, Species.DACHSBUN ]}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ Species.MAUSHOLD ], [TimeOfDay.DAY]: [ Species.MAUSHOLD ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CASTFORM, Species.REVAVROOM ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.FOREST]: { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [ Species.BUTTERFREE, - { 1: [ Species.BELLSPROUT ], 21: [ Species.WEEPINBELL ] }, - { 1: [ Species.COMBEE ], 21: [ Species.VESPIQUEN ] }, + { 1: [ Species.BELLSPROUT ], 21: [ Species.WEEPINBELL ]}, + { 1: [ Species.COMBEE ], 21: [ Species.VESPIQUEN ]}, Species.PETILIL, - { 1: [ Species.DEERLING ], 34: [ Species.SAWSBUCK ] }, + { 1: [ Species.DEERLING ], 34: [ Species.SAWSBUCK ]}, Species.VIVILLON ], [TimeOfDay.DAY]: [ Species.BUTTERFREE, - { 1: [ Species.BELLSPROUT ], 21: [ Species.WEEPINBELL ] }, + { 1: [ Species.BELLSPROUT ], 21: [ Species.WEEPINBELL ]}, Species.BEAUTIFLY, - { 1: [ Species.COMBEE ], 21: [ Species.VESPIQUEN ] }, + { 1: [ Species.COMBEE ], 21: [ Species.VESPIQUEN ]}, Species.PETILIL, - { 1: [ Species.DEERLING ], 34: [ Species.SAWSBUCK ] }, + { 1: [ Species.DEERLING ], 34: [ Species.SAWSBUCK ]}, Species.VIVILLON ], [TimeOfDay.DUSK]: [ Species.BEEDRILL, - { 1: [ Species.PINECO ], 31: [ Species.FORRETRESS ] }, - { 1: [ Species.SEEDOT ], 14: [ Species.NUZLEAF ] }, - { 1: [ Species.SHROOMISH ], 23: [ Species.BRELOOM ] }, - { 1: [ Species.VENIPEDE ], 22: [ Species.WHIRLIPEDE ], 30: [ Species.SCOLIPEDE ] } + { 1: [ Species.PINECO ], 31: [ Species.FORRETRESS ]}, + { 1: [ Species.SEEDOT ], 14: [ Species.NUZLEAF ]}, + { 1: [ Species.SHROOMISH ], 23: [ Species.BRELOOM ]}, + { 1: [ Species.VENIPEDE ], 22: [ Species.WHIRLIPEDE ], 30: [ Species.SCOLIPEDE ]} ], [TimeOfDay.NIGHT]: [ Species.BEEDRILL, - { 1: [ Species.VENONAT ], 31: [ Species.VENOMOTH ] }, - { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ] }, - { 1: [ Species.PINECO ], 31: [ Species.FORRETRESS ] }, + { 1: [ Species.VENONAT ], 31: [ Species.VENOMOTH ]}, + { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ]}, + { 1: [ Species.PINECO ], 31: [ Species.FORRETRESS ]}, Species.DUSTOX, - { 1: [ Species.SEEDOT ], 14: [ Species.NUZLEAF ] }, - { 1: [ Species.SHROOMISH ], 23: [ Species.BRELOOM ] }, - { 1: [ Species.VENIPEDE ], 22: [ Species.WHIRLIPEDE ], 30: [ Species.SCOLIPEDE ] } + { 1: [ Species.SEEDOT ], 14: [ Species.NUZLEAF ]}, + { 1: [ Species.SHROOMISH ], 23: [ Species.BRELOOM ]}, + { 1: [ Species.VENIPEDE ], 22: [ Species.WHIRLIPEDE ], 30: [ Species.SCOLIPEDE ]} ], - [TimeOfDay.ALL]: [ { 1: [ Species.TAROUNTULA ], 15: [ Species.SPIDOPS ] }, { 1: [ Species.NYMBLE ], 24: [ Species.LOKIX ] }, { 1: [ Species.SHROODLE ], 28: [ Species.GRAFAIAI ] } ] + [TimeOfDay.ALL]: [{ 1: [ Species.TAROUNTULA ], 15: [ Species.SPIDOPS ]}, { 1: [ Species.NYMBLE ], 24: [ Species.LOKIX ]}, { 1: [ Species.SHROODLE ], 28: [ Species.GRAFAIAI ]}] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ Species.ROSELIA, Species.MOTHIM, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ] } ], - [TimeOfDay.DAY]: [ Species.ROSELIA, Species.MOTHIM, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ] }, { 1: [ Species.DOTTLER ], 30: [ Species.ORBEETLE ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.HOOTHOOT ], 20: [ Species.NOCTOWL ] }, { 1: [ Species.ROCKRUFF ], 25: [ Species.LYCANROC ] }, { 1: [ Species.DOTTLER ], 30: [ Species.ORBEETLE ] } ], + [TimeOfDay.DAWN]: [ Species.ROSELIA, Species.MOTHIM, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ]}], + [TimeOfDay.DAY]: [ Species.ROSELIA, Species.MOTHIM, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ]}, { 1: [ Species.DOTTLER ], 30: [ Species.ORBEETLE ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.HOOTHOOT ], 20: [ Species.NOCTOWL ]}, { 1: [ Species.ROCKRUFF ], 25: [ Species.LYCANROC ]}, { 1: [ Species.DOTTLER ], 30: [ Species.ORBEETLE ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.EKANS ], 22: [ Species.ARBOK ] }, - { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ] }, - { 1: [ Species.BURMY ], 20: [ Species.WORMADAM ] }, - { 1: [ Species.PANSAGE ], 30: [ Species.SIMISAGE ] } + { 1: [ Species.EKANS ], 22: [ Species.ARBOK ]}, + { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ]}, + { 1: [ Species.BURMY ], 20: [ Species.WORMADAM ]}, + { 1: [ Species.PANSAGE ], 30: [ Species.SIMISAGE ]} ] }, [BiomePoolTier.RARE]: { @@ -366,18 +366,18 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.SCYTHER ], [TimeOfDay.ALL]: [ Species.HERACROSS, - { 1: [ Species.TREECKO ], 16: [ Species.GROVYLE ], 36: [ Species.SCEPTILE ] }, + { 1: [ Species.TREECKO ], 16: [ Species.GROVYLE ], 36: [ Species.SCEPTILE ]}, Species.TROPIUS, Species.KARRABLAST, Species.SHELMET, - { 1: [ Species.CHESPIN ], 16: [ Species.QUILLADIN ], 36: [ Species.CHESNAUGHT ] }, - { 1: [ Species.ROWLET ], 17: [ Species.DARTRIX ], 34: [ Species.DECIDUEYE ] }, + { 1: [ Species.CHESPIN ], 16: [ Species.QUILLADIN ], 36: [ Species.CHESNAUGHT ]}, + { 1: [ Species.ROWLET ], 17: [ Species.DARTRIX ], 34: [ Species.DECIDUEYE ]}, Species.SQUAWKABILLY, - { 1: [ Species.TOEDSCOOL ], 30: [ Species.TOEDSCRUEL ] } + { 1: [ Species.TOEDSCOOL ], 30: [ Species.TOEDSCRUEL ]} ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ Species.BLOODMOON_URSALUNA ], [TimeOfDay.ALL]: [ Species.DURANT ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KARTANA, Species.WO_CHIEN ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ Species.BLOODMOON_URSALUNA ], [TimeOfDay.ALL]: [ Species.DURANT ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KARTANA, Species.WO_CHIEN ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.VICTREEBEL, Species.MOTHIM, Species.VESPIQUEN, Species.LILLIGANT, Species.SAWSBUCK ], [TimeOfDay.DAY]: [ Species.VICTREEBEL, Species.BEAUTIFLY, Species.MOTHIM, Species.VESPIQUEN, Species.LILLIGANT, Species.SAWSBUCK ], @@ -392,29 +392,29 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.LYCANROC, Species.BLOODMOON_URSALUNA ], [TimeOfDay.ALL]: [ Species.HERACROSS, Species.SCEPTILE, Species.ESCAVALIER, Species.ACCELGOR, Species.DURANT, Species.CHESNAUGHT, Species.DECIDUEYE, Species.TOEDSCRUEL ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KARTANA, Species.WO_CHIEN ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CALYREX ] } + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KARTANA, Species.WO_CHIEN ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CALYREX ]} }, [Biome.SEA]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.SLOWPOKE ], 37: [ Species.SLOWBRO ] }, { 1: [ Species.WINGULL ], 25: [ Species.PELIPPER ] }, Species.CRAMORANT, { 1: [ Species.FINIZEN ], 38: [ Species.PALAFIN ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.SLOWPOKE ], 37: [ Species.SLOWBRO ] }, { 1: [ Species.WINGULL ], 25: [ Species.PELIPPER ] }, Species.CRAMORANT, { 1: [ Species.FINIZEN ], 38: [ Species.PALAFIN ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.INKAY ], 30: [ Species.MALAMAR ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.FINNEON ], 31: [ Species.LUMINEON ] }, { 1: [ Species.INKAY ], 30: [ Species.MALAMAR ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.TENTACOOL ], 30: [ Species.TENTACRUEL ] }, { 1: [ Species.MAGIKARP ], 20: [ Species.GYARADOS ] }, { 1: [ Species.BUIZEL ], 26: [ Species.FLOATZEL ] } ] + [TimeOfDay.DAWN]: [{ 1: [ Species.SLOWPOKE ], 37: [ Species.SLOWBRO ]}, { 1: [ Species.WINGULL ], 25: [ Species.PELIPPER ]}, Species.CRAMORANT, { 1: [ Species.FINIZEN ], 38: [ Species.PALAFIN ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.SLOWPOKE ], 37: [ Species.SLOWBRO ]}, { 1: [ Species.WINGULL ], 25: [ Species.PELIPPER ]}, Species.CRAMORANT, { 1: [ Species.FINIZEN ], 38: [ Species.PALAFIN ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.INKAY ], 30: [ Species.MALAMAR ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.FINNEON ], 31: [ Species.LUMINEON ]}, { 1: [ Species.INKAY ], 30: [ Species.MALAMAR ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.TENTACOOL ], 30: [ Species.TENTACRUEL ]}, { 1: [ Species.MAGIKARP ], 20: [ Species.GYARADOS ]}, { 1: [ Species.BUIZEL ], 26: [ Species.FLOATZEL ]}] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.STARYU ], 30: [ Species.STARMIE ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.STARYU ], 30: [ Species.STARMIE ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.SLOWPOKE ], 37: [ Species.SLOWBRO ] }, Species.SHELLDER, { 1: [ Species.CARVANHA ], 30: [ Species.SHARPEDO ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.SLOWPOKE ], 37: [ Species.SLOWBRO ] }, Species.SHELLDER, { 1: [ Species.CHINCHOU ], 27: [ Species.LANTURN ] }, { 1: [ Species.CARVANHA ], 30: [ Species.SHARPEDO ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.STARYU ], 30: [ Species.STARMIE ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.STARYU ], 30: [ Species.STARMIE ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.SLOWPOKE ], 37: [ Species.SLOWBRO ]}, Species.SHELLDER, { 1: [ Species.CARVANHA ], 30: [ Species.SHARPEDO ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.SLOWPOKE ], 37: [ Species.SLOWBRO ]}, Species.SHELLDER, { 1: [ Species.CHINCHOU ], 27: [ Species.LANTURN ]}, { 1: [ Species.CARVANHA ], 30: [ Species.SHARPEDO ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.POLIWAG ], 25: [ Species.POLIWHIRL ] }, - { 1: [ Species.HORSEA ], 32: [ Species.SEADRA ] }, - { 1: [ Species.GOLDEEN ], 33: [ Species.SEAKING ] }, - { 1: [ Species.WAILMER ], 40: [ Species.WAILORD ] }, - { 1: [ Species.PANPOUR ], 30: [ Species.SIMIPOUR ] }, - { 1: [ Species.WATTREL ], 25: [ Species.KILOWATTREL ] } + { 1: [ Species.POLIWAG ], 25: [ Species.POLIWHIRL ]}, + { 1: [ Species.HORSEA ], 32: [ Species.SEADRA ]}, + { 1: [ Species.GOLDEEN ], 33: [ Species.SEAKING ]}, + { 1: [ Species.WAILMER ], 40: [ Species.WAILORD ]}, + { 1: [ Species.PANPOUR ], 30: [ Species.SIMIPOUR ]}, + { 1: [ Species.WATTREL ], 25: [ Species.KILOWATTREL ]} ] }, [BiomePoolTier.RARE]: { @@ -422,10 +422,10 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ Species.LAPRAS, { 1: [ Species.PIPLUP ], 16: [ Species.PRINPLUP ], 36: [ Species.EMPOLEON ] }, { 1: [ Species.POPPLIO ], 17: [ Species.BRIONNE ], 34: [ Species.PRIMARINA ] } ] + [TimeOfDay.ALL]: [ Species.LAPRAS, { 1: [ Species.PIPLUP ], 16: [ Species.PRINPLUP ], 36: [ Species.EMPOLEON ]}, { 1: [ Species.POPPLIO ], 17: [ Species.BRIONNE ], 34: [ Species.PRIMARINA ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KINGDRA, Species.ROTOM, { 1: [ Species.TIRTOUGA ], 37: [ Species.CARRACOSTA ] } ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KINGDRA, Species.ROTOM, { 1: [ Species.TIRTOUGA ], 37: [ Species.CARRACOSTA ]}]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.PELIPPER, Species.CRAMORANT, Species.PALAFIN ], [TimeOfDay.DAY]: [ Species.PELIPPER, Species.CRAMORANT, Species.PALAFIN ], @@ -433,34 +433,34 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.SHARPEDO, Species.LUMINEON, Species.MALAMAR ], [TimeOfDay.ALL]: [ Species.TENTACRUEL, Species.FLOATZEL, Species.SIMIPOUR, Species.KILOWATTREL ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KINGDRA, Species.EMPOLEON, Species.PRIMARINA ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROTOM ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.LUGIA ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KINGDRA, Species.EMPOLEON, Species.PRIMARINA ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROTOM ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.LUGIA ]} }, [Biome.SWAMP]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.WOOPER ], 20: [ Species.QUAGSIRE ] }, { 1: [ Species.LOTAD ], 14: [ Species.LOMBRE ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.WOOPER ], 20: [ Species.QUAGSIRE ] }, { 1: [ Species.LOTAD ], 14: [ Species.LOMBRE ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.EKANS ], 22: [ Species.ARBOK ] }, { 1: [ Species.PALDEA_WOOPER ], 20: [ Species.CLODSIRE ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.EKANS ], 22: [ Species.ARBOK ] }, { 1: [ Species.PALDEA_WOOPER ], 20: [ Species.CLODSIRE ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.WOOPER ], 20: [ Species.QUAGSIRE ]}, { 1: [ Species.LOTAD ], 14: [ Species.LOMBRE ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.WOOPER ], 20: [ Species.QUAGSIRE ]}, { 1: [ Species.LOTAD ], 14: [ Species.LOMBRE ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.EKANS ], 22: [ Species.ARBOK ]}, { 1: [ Species.PALDEA_WOOPER ], 20: [ Species.CLODSIRE ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.EKANS ], 22: [ Species.ARBOK ]}, { 1: [ Species.PALDEA_WOOPER ], 20: [ Species.CLODSIRE ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.POLIWAG ], 25: [ Species.POLIWHIRL ] }, - { 1: [ Species.GULPIN ], 26: [ Species.SWALOT ] }, - { 1: [ Species.SHELLOS ], 30: [ Species.GASTRODON ] }, - { 1: [ Species.TYMPOLE ], 25: [ Species.PALPITOAD ], 36: [ Species.SEISMITOAD ] } + { 1: [ Species.POLIWAG ], 25: [ Species.POLIWHIRL ]}, + { 1: [ Species.GULPIN ], 26: [ Species.SWALOT ]}, + { 1: [ Species.SHELLOS ], 30: [ Species.GASTRODON ]}, + { 1: [ Species.TYMPOLE ], 25: [ Species.PALPITOAD ], 36: [ Species.SEISMITOAD ]} ] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.EKANS ], 22: [ Species.ARBOK ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.EKANS ], 22: [ Species.ARBOK ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.CROAGUNK ], 37: [ Species.TOXICROAK ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.CROAGUNK ], 37: [ Species.TOXICROAK ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.EKANS ], 22: [ Species.ARBOK ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.EKANS ], 22: [ Species.ARBOK ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.CROAGUNK ], 37: [ Species.TOXICROAK ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.CROAGUNK ], 37: [ Species.TOXICROAK ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.PSYDUCK ], 33: [ Species.GOLDUCK ] }, - { 1: [ Species.BARBOACH ], 30: [ Species.WHISCASH ] }, - { 1: [ Species.SKORUPI ], 40: [ Species.DRAPION ] }, + { 1: [ Species.PSYDUCK ], 33: [ Species.GOLDUCK ]}, + { 1: [ Species.BARBOACH ], 30: [ Species.WHISCASH ]}, + { 1: [ Species.SKORUPI ], 40: [ Species.DRAPION ]}, Species.STUNFISK, - { 1: [ Species.MAREANIE ], 38: [ Species.TOXAPEX ] } + { 1: [ Species.MAREANIE ], 38: [ Species.TOXAPEX ]} ] }, [BiomePoolTier.RARE]: { @@ -468,16 +468,16 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ { 1: [ Species.TOTODILE ], 18: [ Species.CROCONAW ], 30: [ Species.FERALIGATR ] }, { 1: [ Species.MUDKIP ], 16: [ Species.MARSHTOMP ], 36: [ Species.SWAMPERT ] } ] + [TimeOfDay.ALL]: [{ 1: [ Species.TOTODILE ], 18: [ Species.CROCONAW ], 30: [ Species.FERALIGATR ]}, { 1: [ Species.MUDKIP ], 16: [ Species.MARSHTOMP ], 36: [ Species.SWAMPERT ]}] }, [BiomePoolTier.SUPER_RARE]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.GALAR_SLOWPOKE ], 40: [ Species.GALAR_SLOWBRO ] }, { 1: [ Species.HISUI_SLIGGOO ], 80: [ Species.HISUI_GOODRA ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.GALAR_SLOWPOKE ], 40: [ Species.GALAR_SLOWBRO ] }, { 1: [ Species.HISUI_SLIGGOO ], 80: [ Species.HISUI_GOODRA ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.GALAR_SLOWPOKE ], 40: [ Species.GALAR_SLOWBRO ]}, { 1: [ Species.HISUI_SLIGGOO ], 80: [ Species.HISUI_GOODRA ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.GALAR_SLOWPOKE ], 40: [ Species.GALAR_SLOWBRO ]}, { 1: [ Species.HISUI_SLIGGOO ], 80: [ Species.HISUI_GOODRA ]}], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.POLITOED, Species.GALAR_STUNFISK ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.AZELF, Species.POIPOLE ] }, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.AZELF, Species.POIPOLE ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.QUAGSIRE, Species.LUDICOLO ], [TimeOfDay.DAY]: [ Species.QUAGSIRE, Species.LUDICOLO ], @@ -492,22 +492,22 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.FERALIGATR, Species.POLITOED, Species.SWAMPERT, Species.GALAR_STUNFISK ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.AZELF, Species.NAGANADEL ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.AZELF, Species.NAGANADEL ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.BEACH]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.STARYU ], 30: [ Species.STARMIE ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.STARYU ], 30: [ Species.STARMIE ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.STARYU ], 30: [ Species.STARMIE ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.STARYU ], 30: [ Species.STARMIE ]}], [TimeOfDay.DUSK]: [ Species.SHELLDER ], [TimeOfDay.NIGHT]: [ Species.SHELLDER ], [TimeOfDay.ALL]: [ - { 1: [ Species.KRABBY ], 28: [ Species.KINGLER ] }, - { 1: [ Species.CORPHISH ], 30: [ Species.CRAWDAUNT ] }, - { 1: [ Species.DWEBBLE ], 34: [ Species.CRUSTLE ] }, - { 1: [ Species.BINACLE ], 39: [ Species.BARBARACLE ] }, - { 1: [ Species.MAREANIE ], 38: [ Species.TOXAPEX ] }, - { 1: [ Species.WIGLETT ], 26: [ Species.WUGTRIO ] } + { 1: [ Species.KRABBY ], 28: [ Species.KINGLER ]}, + { 1: [ Species.CORPHISH ], 30: [ Species.CRAWDAUNT ]}, + { 1: [ Species.DWEBBLE ], 34: [ Species.CRUSTLE ]}, + { 1: [ Species.BINACLE ], 39: [ Species.BARBARACLE ]}, + { 1: [ Species.MAREANIE ], 38: [ Species.TOXAPEX ]}, + { 1: [ Species.WIGLETT ], 26: [ Species.WUGTRIO ]} ] }, [BiomePoolTier.UNCOMMON]: { @@ -515,11 +515,11 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ { 1: [ Species.BURMY ], 20: [ Species.WORMADAM ] }, { 1: [ Species.CLAUNCHER ], 37: [ Species.CLAWITZER ] }, { 1: [ Species.SANDYGAST ], 42: [ Species.PALOSSAND ] } ] + [TimeOfDay.ALL]: [{ 1: [ Species.BURMY ], 20: [ Species.WORMADAM ]}, { 1: [ Species.CLAUNCHER ], 37: [ Species.CLAWITZER ]}, { 1: [ Species.SANDYGAST ], 42: [ Species.PALOSSAND ]}] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.QUAXLY ], 16: [ Species.QUAXWELL ], 36: [ Species.QUAQUAVAL ] }, Species.TATSUGIRI ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.TIRTOUGA ], 37: [ Species.CARRACOSTA ] } ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CRESSELIA, Species.KELDEO, Species.TAPU_FINI ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.QUAXLY ], 16: [ Species.QUAXWELL ], 36: [ Species.QUAQUAVAL ]}, Species.TATSUGIRI ]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.TIRTOUGA ], 37: [ Species.CARRACOSTA ]}]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CRESSELIA, Species.KELDEO, Species.TAPU_FINI ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.STARMIE ], [TimeOfDay.DAY]: [ Species.STARMIE ], @@ -527,29 +527,29 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.CLOYSTER ], [TimeOfDay.ALL]: [ Species.KINGLER, Species.CRAWDAUNT, Species.WORMADAM, Species.CRUSTLE, Species.BARBARACLE, Species.CLAWITZER, Species.TOXAPEX, Species.PALOSSAND ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CARRACOSTA, Species.QUAQUAVAL ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CRESSELIA, Species.KELDEO, Species.TAPU_FINI ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CARRACOSTA, Species.QUAQUAVAL ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CRESSELIA, Species.KELDEO, Species.TAPU_FINI ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.LAKE]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.LOTAD ], 14: [ Species.LOMBRE ] }, { 1: [ Species.DUCKLETT ], 35: [ Species.SWANNA ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.LOTAD ], 14: [ Species.LOMBRE ] }, { 1: [ Species.DUCKLETT ], 35: [ Species.SWANNA ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.MARILL ], 18: [ Species.AZUMARILL ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.MARILL ], 18: [ Species.AZUMARILL ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.LOTAD ], 14: [ Species.LOMBRE ]}, { 1: [ Species.DUCKLETT ], 35: [ Species.SWANNA ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.LOTAD ], 14: [ Species.LOMBRE ]}, { 1: [ Species.DUCKLETT ], 35: [ Species.SWANNA ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.MARILL ], 18: [ Species.AZUMARILL ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.MARILL ], 18: [ Species.AZUMARILL ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.PSYDUCK ], 33: [ Species.GOLDUCK ] }, - { 1: [ Species.GOLDEEN ], 33: [ Species.SEAKING ] }, - { 1: [ Species.MAGIKARP ], 20: [ Species.GYARADOS ] }, - { 1: [ Species.CHEWTLE ], 22: [ Species.DREDNAW ] } + { 1: [ Species.PSYDUCK ], 33: [ Species.GOLDUCK ]}, + { 1: [ Species.GOLDEEN ], 33: [ Species.SEAKING ]}, + { 1: [ Species.MAGIKARP ], 20: [ Species.GYARADOS ]}, + { 1: [ Species.CHEWTLE ], 22: [ Species.DREDNAW ]} ] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.DEWPIDER ], 22: [ Species.ARAQUANID ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.DEWPIDER ], 22: [ Species.ARAQUANID ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.DEWPIDER ], 22: [ Species.ARAQUANID ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.DEWPIDER ], 22: [ Species.ARAQUANID ]}], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ { 1: [ Species.SLOWPOKE ], 37: [ Species.SLOWBRO ] }, { 1: [ Species.WOOPER ], 20: [ Species.QUAGSIRE ] }, { 1: [ Species.SURSKIT ], 22: [ Species.MASQUERAIN ] }, Species.WISHIWASHI, Species.FLAMIGO ] + [TimeOfDay.ALL]: [{ 1: [ Species.SLOWPOKE ], 37: [ Species.SLOWBRO ]}, { 1: [ Species.WOOPER ], 20: [ Species.QUAGSIRE ]}, { 1: [ Species.SURSKIT ], 22: [ Species.MASQUERAIN ]}, Species.WISHIWASHI, Species.FLAMIGO ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], @@ -557,14 +557,14 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.SQUIRTLE ], 16: [ Species.WARTORTLE ], 36: [ Species.BLASTOISE ] }, - { 1: [ Species.OSHAWOTT ], 17: [ Species.DEWOTT ], 36: [ Species.SAMUROTT ] }, - { 1: [ Species.FROAKIE ], 16: [ Species.FROGADIER ], 36: [ Species.GRENINJA ] }, - { 1: [ Species.SOBBLE ], 16: [ Species.DRIZZILE ], 35: [ Species.INTELEON ] } + { 1: [ Species.SQUIRTLE ], 16: [ Species.WARTORTLE ], 36: [ Species.BLASTOISE ]}, + { 1: [ Species.OSHAWOTT ], 17: [ Species.DEWOTT ], 36: [ Species.SAMUROTT ]}, + { 1: [ Species.FROAKIE ], 16: [ Species.FROGADIER ], 36: [ Species.GRENINJA ]}, + { 1: [ Species.SOBBLE ], 16: [ Species.DRIZZILE ], 35: [ Species.INTELEON ]} ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.VAPOREON, Species.SLOWKING ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SUICUNE, Species.MESPRIT ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.VAPOREON, Species.SLOWKING ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SUICUNE, Species.MESPRIT ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.SWANNA, Species.ARAQUANID ], [TimeOfDay.DAY]: [ Species.SWANNA, Species.ARAQUANID ], @@ -572,9 +572,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.AZUMARILL ], [TimeOfDay.ALL]: [ Species.GOLDUCK, Species.SLOWBRO, Species.SEAKING, Species.GYARADOS, Species.MASQUERAIN, Species.WISHIWASHI, Species.DREDNAW ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.BLASTOISE, Species.VAPOREON, Species.SLOWKING, Species.SAMUROTT, Species.GRENINJA, Species.INTELEON ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SUICUNE, Species.MESPRIT ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.BLASTOISE, Species.VAPOREON, Species.SLOWKING, Species.SAMUROTT, Species.GRENINJA, Species.INTELEON ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SUICUNE, Species.MESPRIT ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.SEABED]: { [BiomePoolTier.COMMON]: { @@ -583,12 +583,12 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.CHINCHOU ], 27: [ Species.LANTURN ] }, + { 1: [ Species.CHINCHOU ], 27: [ Species.LANTURN ]}, Species.REMORAID, Species.CLAMPERL, Species.BASCULIN, - { 1: [ Species.FRILLISH ], 40: [ Species.JELLICENT ] }, - { 1: [ Species.ARROKUDA ], 26: [ Species.BARRASKEWDA ] }, + { 1: [ Species.FRILLISH ], 40: [ Species.JELLICENT ]}, + { 1: [ Species.ARROKUDA ], 26: [ Species.BARRASKEWDA ]}, Species.VELUZA ] }, @@ -598,12 +598,12 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.TENTACOOL ], 30: [ Species.TENTACRUEL ] }, + { 1: [ Species.TENTACOOL ], 30: [ Species.TENTACRUEL ]}, Species.SHELLDER, - { 1: [ Species.WAILMER ], 40: [ Species.WAILORD ] }, + { 1: [ Species.WAILMER ], 40: [ Species.WAILORD ]}, Species.LUVDISC, - { 1: [ Species.SHELLOS ], 30: [ Species.GASTRODON ] }, - { 1: [ Species.SKRELP ], 48: [ Species.DRAGALGE ] }, + { 1: [ Species.SHELLOS ], 30: [ Species.GASTRODON ]}, + { 1: [ Species.SKRELP ], 48: [ Species.DRAGALGE ]}, Species.PINCURCHIN, Species.DONDOZO ] @@ -613,7 +613,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ Species.QWILFISH, Species.CORSOLA, Species.OCTILLERY, { 1: [ Species.MANTYKE ], 52: [ Species.MANTINE ] }, Species.ALOMOMOLA, { 1: [ Species.TYNAMO ], 39: [ Species.EELEKTRIK ] }, Species.DHELMISE ] + [TimeOfDay.ALL]: [ Species.QWILFISH, Species.CORSOLA, Species.OCTILLERY, { 1: [ Species.MANTYKE ], 52: [ Species.MANTINE ]}, Species.ALOMOMOLA, { 1: [ Species.TYNAMO ], 39: [ Species.EELEKTRIK ]}, Species.DHELMISE ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], @@ -621,16 +621,16 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.OMANYTE ], 40: [ Species.OMASTAR ] }, - { 1: [ Species.KABUTO ], 40: [ Species.KABUTOPS ] }, + { 1: [ Species.OMANYTE ], 40: [ Species.OMASTAR ]}, + { 1: [ Species.KABUTO ], 40: [ Species.KABUTOPS ]}, Species.RELICANTH, Species.PYUKUMUKU, - { 1: [ Species.GALAR_CORSOLA ], 38: [ Species.CURSOLA ] }, + { 1: [ Species.GALAR_CORSOLA ], 38: [ Species.CURSOLA ]}, Species.ARCTOVISH, Species.HISUI_QWILFISH ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.FEEBAS, Species.NIHILEGO ] }, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.FEEBAS, Species.NIHILEGO ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], @@ -645,56 +645,56 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.OMASTAR, Species.KABUTOPS, Species.RELICANTH, Species.EELEKTROSS, Species.PYUKUMUKU, Species.DHELMISE, Species.CURSOLA, Species.ARCTOVISH, Species.BASCULEGION, Species.OVERQWIL ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MILOTIC, Species.NIHILEGO ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KYOGRE ] } + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MILOTIC, Species.NIHILEGO ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KYOGRE ]} }, [Biome.MOUNTAIN]: { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [ - { 1: [ Species.TAILLOW ], 22: [ Species.SWELLOW ] }, - { 1: [ Species.SWABLU ], 35: [ Species.ALTARIA ] }, - { 1: [ Species.STARLY ], 14: [ Species.STARAVIA ], 34: [ Species.STARAPTOR ] }, - { 1: [ Species.PIDOVE ], 21: [ Species.TRANQUILL ], 32: [ Species.UNFEZANT ] }, - { 1: [ Species.FLETCHLING ], 17: [ Species.FLETCHINDER ], 35: [ Species.TALONFLAME ] } + { 1: [ Species.TAILLOW ], 22: [ Species.SWELLOW ]}, + { 1: [ Species.SWABLU ], 35: [ Species.ALTARIA ]}, + { 1: [ Species.STARLY ], 14: [ Species.STARAVIA ], 34: [ Species.STARAPTOR ]}, + { 1: [ Species.PIDOVE ], 21: [ Species.TRANQUILL ], 32: [ Species.UNFEZANT ]}, + { 1: [ Species.FLETCHLING ], 17: [ Species.FLETCHINDER ], 35: [ Species.TALONFLAME ]} ], [TimeOfDay.DAY]: [ - { 1: [ Species.TAILLOW ], 22: [ Species.SWELLOW ] }, - { 1: [ Species.SWABLU ], 35: [ Species.ALTARIA ] }, - { 1: [ Species.STARLY ], 14: [ Species.STARAVIA ], 34: [ Species.STARAPTOR ] }, - { 1: [ Species.PIDOVE ], 21: [ Species.TRANQUILL ], 32: [ Species.UNFEZANT ] }, - { 1: [ Species.FLETCHLING ], 17: [ Species.FLETCHINDER ], 35: [ Species.TALONFLAME ] } + { 1: [ Species.TAILLOW ], 22: [ Species.SWELLOW ]}, + { 1: [ Species.SWABLU ], 35: [ Species.ALTARIA ]}, + { 1: [ Species.STARLY ], 14: [ Species.STARAVIA ], 34: [ Species.STARAPTOR ]}, + { 1: [ Species.PIDOVE ], 21: [ Species.TRANQUILL ], 32: [ Species.UNFEZANT ]}, + { 1: [ Species.FLETCHLING ], 17: [ Species.FLETCHINDER ], 35: [ Species.TALONFLAME ]} ], - [TimeOfDay.DUSK]: [ { 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ] }, { 1: [ Species.ARON ], 32: [ Species.LAIRON ], 42: [ Species.AGGRON ] }, { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ] }, { 1: [ Species.ARON ], 32: [ Species.LAIRON ], 42: [ Species.AGGRON ] }, { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.PIDGEY ], 18: [ Species.PIDGEOTTO ], 36: [ Species.PIDGEOT ] }, { 1: [ Species.SPEAROW ], 20: [ Species.FEAROW ] }, { 1: [ Species.SKIDDO ], 32: [ Species.GOGOAT ] } ] + [TimeOfDay.DUSK]: [{ 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ]}, { 1: [ Species.ARON ], 32: [ Species.LAIRON ], 42: [ Species.AGGRON ]}, { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ]}, { 1: [ Species.ARON ], 32: [ Species.LAIRON ], 42: [ Species.AGGRON ]}, { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.PIDGEY ], 18: [ Species.PIDGEOTTO ], 36: [ Species.PIDGEOT ]}, { 1: [ Species.SPEAROW ], 20: [ Species.FEAROW ]}, { 1: [ Species.SKIDDO ], 32: [ Species.GOGOAT ]}] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [ - { 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ] }, - { 1: [ Species.ARON ], 32: [ Species.LAIRON ], 42: [ Species.AGGRON ] }, - { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ] }, - { 1: [ Species.RUFFLET ], 54: [ Species.BRAVIARY ] }, - { 1: [ Species.ROOKIDEE ], 18: [ Species.CORVISQUIRE ], 38: [ Species.CORVIKNIGHT ] }, - { 1: [ Species.FLITTLE ], 35: [ Species.ESPATHRA ] }, + { 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ]}, + { 1: [ Species.ARON ], 32: [ Species.LAIRON ], 42: [ Species.AGGRON ]}, + { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ]}, + { 1: [ Species.RUFFLET ], 54: [ Species.BRAVIARY ]}, + { 1: [ Species.ROOKIDEE ], 18: [ Species.CORVISQUIRE ], 38: [ Species.CORVIKNIGHT ]}, + { 1: [ Species.FLITTLE ], 35: [ Species.ESPATHRA ]}, Species.BOMBIRDIER ], [TimeOfDay.DAY]: [ - { 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ] }, - { 1: [ Species.ARON ], 32: [ Species.LAIRON ], 42: [ Species.AGGRON ] }, - { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ] }, - { 1: [ Species.RUFFLET ], 54: [ Species.BRAVIARY ] }, - { 1: [ Species.ROOKIDEE ], 18: [ Species.CORVISQUIRE ], 38: [ Species.CORVIKNIGHT ] }, - { 1: [ Species.FLITTLE ], 35: [ Species.ESPATHRA ] }, + { 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ]}, + { 1: [ Species.ARON ], 32: [ Species.LAIRON ], 42: [ Species.AGGRON ]}, + { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ]}, + { 1: [ Species.RUFFLET ], 54: [ Species.BRAVIARY ]}, + { 1: [ Species.ROOKIDEE ], 18: [ Species.CORVISQUIRE ], 38: [ Species.CORVIKNIGHT ]}, + { 1: [ Species.FLITTLE ], 35: [ Species.ESPATHRA ]}, Species.BOMBIRDIER ], - [TimeOfDay.DUSK]: [ { 1: [ Species.VULLABY ], 54: [ Species.MANDIBUZZ ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.VULLABY ], 54: [ Species.MANDIBUZZ ] } ], + [TimeOfDay.DUSK]: [{ 1: [ Species.VULLABY ], 54: [ Species.MANDIBUZZ ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.VULLABY ], 54: [ Species.MANDIBUZZ ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.MACHOP ], 28: [ Species.MACHOKE ] }, - { 1: [ Species.GEODUDE ], 25: [ Species.GRAVELER ] }, - { 1: [ Species.NATU ], 25: [ Species.XATU ] }, - { 1: [ Species.SLUGMA ], 38: [ Species.MAGCARGO ] }, - { 1: [ Species.NACLI ], 24: [ Species.NACLSTACK ], 38: [ Species.GARGANACL ] } + { 1: [ Species.MACHOP ], 28: [ Species.MACHOKE ]}, + { 1: [ Species.GEODUDE ], 25: [ Species.GRAVELER ]}, + { 1: [ Species.NATU ], 25: [ Species.XATU ]}, + { 1: [ Species.SLUGMA ], 38: [ Species.MAGCARGO ]}, + { 1: [ Species.NACLI ], 24: [ Species.NACLSTACK ], 38: [ Species.GARGANACL ]} ] }, [BiomePoolTier.RARE]: { @@ -702,7 +702,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ Species.MURKROW ], - [TimeOfDay.ALL]: [ Species.SKARMORY, { 1: [ Species.TORCHIC ], 16: [ Species.COMBUSKEN ], 36: [ Species.BLAZIKEN ] }, { 1: [ Species.SPOINK ], 32: [ Species.GRUMPIG ] }, Species.HAWLUCHA, Species.KLAWF ] + [TimeOfDay.ALL]: [ Species.SKARMORY, { 1: [ Species.TORCHIC ], 16: [ Species.COMBUSKEN ], 36: [ Species.BLAZIKEN ]}, { 1: [ Species.SPOINK ], 32: [ Species.GRUMPIG ]}, Species.HAWLUCHA, Species.KLAWF ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], @@ -710,16 +710,16 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.LARVITAR ], 30: [ Species.PUPITAR ] }, - { 1: [ Species.CRANIDOS ], 30: [ Species.RAMPARDOS ] }, - { 1: [ Species.SHIELDON ], 30: [ Species.BASTIODON ] }, - { 1: [ Species.GIBLE ], 24: [ Species.GABITE ], 48: [ Species.GARCHOMP ] }, + { 1: [ Species.LARVITAR ], 30: [ Species.PUPITAR ]}, + { 1: [ Species.CRANIDOS ], 30: [ Species.RAMPARDOS ]}, + { 1: [ Species.SHIELDON ], 30: [ Species.BASTIODON ]}, + { 1: [ Species.GIBLE ], 24: [ Species.GABITE ], 48: [ Species.GARCHOMP ]}, Species.ROTOM, Species.ARCHEOPS, - { 1: [ Species.AXEW ], 38: [ Species.FRAXURE ] } + { 1: [ Species.AXEW ], 38: [ Species.FRAXURE ]} ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TORNADUS, Species.TING_LU, Species.OGERPON ] }, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TORNADUS, Species.TING_LU, Species.OGERPON ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.SWELLOW, Species.ALTARIA, Species.STARAPTOR, Species.UNFEZANT, Species.BRAVIARY, Species.TALONFLAME, Species.CORVIKNIGHT, Species.ESPATHRA ], [TimeOfDay.DAY]: [ Species.SWELLOW, Species.ALTARIA, Species.STARAPTOR, Species.UNFEZANT, Species.BRAVIARY, Species.TALONFLAME, Species.CORVIKNIGHT, Species.ESPATHRA ], @@ -727,39 +727,39 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.MANDIBUZZ ], [TimeOfDay.ALL]: [ Species.PIDGEOT, Species.FEAROW, Species.SKARMORY, Species.AGGRON, Species.GOGOAT, Species.GARGANACL ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ Species.HISUI_BRAVIARY ], [TimeOfDay.DAY]: [ Species.HISUI_BRAVIARY ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.BLAZIKEN, Species.RAMPARDOS, Species.BASTIODON, Species.HAWLUCHA ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROTOM, Species.TORNADUS, Species.TING_LU, Species.OGERPON ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HO_OH ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ Species.HISUI_BRAVIARY ], [TimeOfDay.DAY]: [ Species.HISUI_BRAVIARY ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.BLAZIKEN, Species.RAMPARDOS, Species.BASTIODON, Species.HAWLUCHA ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROTOM, Species.TORNADUS, Species.TING_LU, Species.OGERPON ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HO_OH ]} }, [Biome.BADLANDS]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.PHANPY ], 25: [ Species.DONPHAN ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.PHANPY ], 25: [ Species.DONPHAN ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.PHANPY ], 25: [ Species.DONPHAN ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.PHANPY ], 25: [ Species.DONPHAN ]}], [TimeOfDay.DUSK]: [], - [TimeOfDay.NIGHT]: [ { 1: [ Species.CUBONE ], 28: [ Species.MAROWAK ] } ], + [TimeOfDay.NIGHT]: [{ 1: [ Species.CUBONE ], 28: [ Species.MAROWAK ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.DIGLETT ], 26: [ Species.DUGTRIO ] }, - { 1: [ Species.GEODUDE ], 25: [ Species.GRAVELER ] }, - { 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ] }, - { 1: [ Species.DRILBUR ], 31: [ Species.EXCADRILL ] }, - { 1: [ Species.MUDBRAY ], 30: [ Species.MUDSDALE ] } + { 1: [ Species.DIGLETT ], 26: [ Species.DUGTRIO ]}, + { 1: [ Species.GEODUDE ], 25: [ Species.GRAVELER ]}, + { 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ]}, + { 1: [ Species.DRILBUR ], 31: [ Species.EXCADRILL ]}, + { 1: [ Species.MUDBRAY ], 30: [ Species.MUDSDALE ]} ] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.SIZZLIPEDE ], 28: [ Species.CENTISKORCH ] }, { 1: [ Species.CAPSAKID ], 30: [ Species.SCOVILLAIN ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.SIZZLIPEDE ], 28: [ Species.CENTISKORCH ] }, { 1: [ Species.CAPSAKID ], 30: [ Species.SCOVILLAIN ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.SIZZLIPEDE ], 28: [ Species.CENTISKORCH ]}, { 1: [ Species.CAPSAKID ], 30: [ Species.SCOVILLAIN ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.SIZZLIPEDE ], 28: [ Species.CENTISKORCH ]}, { 1: [ Species.CAPSAKID ], 30: [ Species.SCOVILLAIN ]}], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.SANDSHREW ], 22: [ Species.SANDSLASH ] }, - { 1: [ Species.NUMEL ], 33: [ Species.CAMERUPT ] }, - { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ] }, - { 1: [ Species.CUFANT ], 34: [ Species.COPPERAJAH ] } + { 1: [ Species.SANDSHREW ], 22: [ Species.SANDSLASH ]}, + { 1: [ Species.NUMEL ], 33: [ Species.CAMERUPT ]}, + { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ]}, + { 1: [ Species.CUFANT ], 34: [ Species.COPPERAJAH ]} ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ONIX, Species.GLIGAR, { 1: [ Species.POLTCHAGEIST ], 30: [ Species.SINISTCHA ] } ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.LANDORUS, Species.OKIDOGI ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ONIX, Species.GLIGAR, { 1: [ Species.POLTCHAGEIST ], 30: [ Species.SINISTCHA ]}]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.LANDORUS, Species.OKIDOGI ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.DONPHAN, Species.CENTISKORCH, Species.SCOVILLAIN ], [TimeOfDay.DAY]: [ Species.DONPHAN, Species.CENTISKORCH, Species.SCOVILLAIN ], @@ -767,9 +767,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.MAROWAK ], [TimeOfDay.ALL]: [ Species.DUGTRIO, Species.GOLEM, Species.RHYPERIOR, Species.GLISCOR, Species.EXCADRILL, Species.MUDSDALE, Species.COPPERAJAH ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.STEELIX, Species.SINISTCHA ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.LANDORUS, Species.OKIDOGI ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GROUDON ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.STEELIX, Species.SINISTCHA ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.LANDORUS, Species.OKIDOGI ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GROUDON ]} }, [Biome.CAVE]: { [BiomePoolTier.COMMON]: { @@ -778,27 +778,27 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.ZUBAT ], 22: [ Species.GOLBAT ] }, - { 1: [ Species.PARAS ], 24: [ Species.PARASECT ] }, - { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ] }, - { 1: [ Species.WHISMUR ], 20: [ Species.LOUDRED ], 40: [ Species.EXPLOUD ] }, - { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ] }, - { 1: [ Species.WOOBAT ], 20: [ Species.SWOOBAT ] }, - { 1: [ Species.BUNNELBY ], 20: [ Species.DIGGERSBY ] }, - { 1: [ Species.NACLI ], 24: [ Species.NACLSTACK ], 38: [ Species.GARGANACL ] } + { 1: [ Species.ZUBAT ], 22: [ Species.GOLBAT ]}, + { 1: [ Species.PARAS ], 24: [ Species.PARASECT ]}, + { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ]}, + { 1: [ Species.WHISMUR ], 20: [ Species.LOUDRED ], 40: [ Species.EXPLOUD ]}, + { 1: [ Species.ROGGENROLA ], 25: [ Species.BOLDORE ]}, + { 1: [ Species.WOOBAT ], 20: [ Species.SWOOBAT ]}, + { 1: [ Species.BUNNELBY ], 20: [ Species.DIGGERSBY ]}, + { 1: [ Species.NACLI ], 24: [ Species.NACLSTACK ], 38: [ Species.GARGANACL ]} ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ { 1: [ Species.ROCKRUFF ], 25: [ Species.LYCANROC ] } ], + [TimeOfDay.DUSK]: [{ 1: [ Species.ROCKRUFF ], 25: [ Species.LYCANROC ]}], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.GEODUDE ], 25: [ Species.GRAVELER ] }, - { 1: [ Species.MAKUHITA ], 24: [ Species.HARIYAMA ] }, + { 1: [ Species.GEODUDE ], 25: [ Species.GRAVELER ]}, + { 1: [ Species.MAKUHITA ], 24: [ Species.HARIYAMA ]}, Species.NOSEPASS, - { 1: [ Species.NOIBAT ], 48: [ Species.NOIVERN ] }, - { 1: [ Species.WIMPOD ], 30: [ Species.GOLISOPOD ] } + { 1: [ Species.NOIBAT ], 48: [ Species.NOIVERN ]}, + { 1: [ Species.WIMPOD ], 30: [ Species.GOLISOPOD ]} ] }, [BiomePoolTier.RARE]: { @@ -806,10 +806,10 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ Species.ONIX, { 1: [ Species.FERROSEED ], 40: [ Species.FERROTHORN ] }, Species.CARBINK, { 1: [ Species.GLIMMET ], 35: [ Species.GLIMMORA ] } ] + [TimeOfDay.ALL]: [ Species.ONIX, { 1: [ Species.FERROSEED ], 40: [ Species.FERROTHORN ]}, Species.CARBINK, { 1: [ Species.GLIMMET ], 35: [ Species.GLIMMORA ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SHUCKLE ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.UXIE ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SHUCKLE ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.UXIE ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], @@ -817,34 +817,34 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.PARASECT, Species.ONIX, Species.CROBAT, Species.URSARING, Species.EXPLOUD, Species.PROBOPASS, Species.GIGALITH, Species.SWOOBAT, Species.DIGGERSBY, Species.NOIVERN, Species.GOLISOPOD, Species.GARGANACL ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ Species.LYCANROC ], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SHUCKLE, Species.FERROTHORN, Species.GLIMMORA ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.UXIE ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TERAPAGOS ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ Species.LYCANROC ], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SHUCKLE, Species.FERROTHORN, Species.GLIMMORA ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.UXIE ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TERAPAGOS ]} }, [Biome.DESERT]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ Species.TRAPINCH, { 1: [ Species.HIPPOPOTAS ], 34: [ Species.HIPPOWDON ] }, { 1: [ Species.RELLOR ], 29: [ Species.RABSCA ] } ], - [TimeOfDay.DAY]: [ Species.TRAPINCH, { 1: [ Species.HIPPOPOTAS ], 34: [ Species.HIPPOWDON ] }, { 1: [ Species.RELLOR ], 29: [ Species.RABSCA ] } ], - [TimeOfDay.DUSK]: [ { 1: [ Species.CACNEA ], 32: [ Species.CACTURNE ] }, { 1: [ Species.SANDILE ], 29: [ Species.KROKOROK ], 40: [ Species.KROOKODILE ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.CACNEA ], 32: [ Species.CACTURNE ] }, { 1: [ Species.SANDILE ], 29: [ Species.KROKOROK ], 40: [ Species.KROOKODILE ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.SANDSHREW ], 22: [ Species.SANDSLASH ] }, { 1: [ Species.SKORUPI ], 40: [ Species.DRAPION ] }, { 1: [ Species.SILICOBRA ], 36: [ Species.SANDACONDA ] } ] + [TimeOfDay.DAWN]: [ Species.TRAPINCH, { 1: [ Species.HIPPOPOTAS ], 34: [ Species.HIPPOWDON ]}, { 1: [ Species.RELLOR ], 29: [ Species.RABSCA ]}], + [TimeOfDay.DAY]: [ Species.TRAPINCH, { 1: [ Species.HIPPOPOTAS ], 34: [ Species.HIPPOWDON ]}, { 1: [ Species.RELLOR ], 29: [ Species.RABSCA ]}], + [TimeOfDay.DUSK]: [{ 1: [ Species.CACNEA ], 32: [ Species.CACTURNE ]}, { 1: [ Species.SANDILE ], 29: [ Species.KROKOROK ], 40: [ Species.KROOKODILE ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.CACNEA ], 32: [ Species.CACTURNE ]}, { 1: [ Species.SANDILE ], 29: [ Species.KROKOROK ], 40: [ Species.KROOKODILE ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.SANDSHREW ], 22: [ Species.SANDSLASH ]}, { 1: [ Species.SKORUPI ], 40: [ Species.DRAPION ]}, { 1: [ Species.SILICOBRA ], 36: [ Species.SANDACONDA ]}] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.SANDILE ], 29: [ Species.KROKOROK ], 40: [ Species.KROOKODILE ] }, Species.HELIOPTILE ], - [TimeOfDay.DAY]: [ { 1: [ Species.SANDILE ], 29: [ Species.KROKOROK ], 40: [ Species.KROOKODILE ] }, Species.HELIOPTILE ], + [TimeOfDay.DAWN]: [{ 1: [ Species.SANDILE ], 29: [ Species.KROKOROK ], 40: [ Species.KROOKODILE ]}, Species.HELIOPTILE ], + [TimeOfDay.DAY]: [{ 1: [ Species.SANDILE ], 29: [ Species.KROKOROK ], 40: [ Species.KROOKODILE ]}, Species.HELIOPTILE ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ Species.MARACTUS, { 1: [ Species.BRAMBLIN ], 30: [ Species.BRAMBLEGHAST ] }, Species.ORTHWORM ] + [TimeOfDay.ALL]: [ Species.MARACTUS, { 1: [ Species.BRAMBLIN ], 30: [ Species.BRAMBLEGHAST ]}, Species.ORTHWORM ] }, [BiomePoolTier.RARE]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.VIBRAVA ], 45: [ Species.FLYGON ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.VIBRAVA ], 45: [ Species.FLYGON ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.VIBRAVA ], 45: [ Species.FLYGON ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.VIBRAVA ], 45: [ Species.FLYGON ]}], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ { 1: [ Species.DARUMAKA ], 35: [ Species.DARMANITAN ] } ] + [TimeOfDay.ALL]: [{ 1: [ Species.DARUMAKA ], 35: [ Species.DARMANITAN ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.LILEEP ], 40: [ Species.CRADILY ] }, { 1: [ Species.ANORITH ], 40: [ Species.ARMALDO ] } ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGIROCK, Species.TAPU_BULU, Species.PHEROMOSA ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.LILEEP ], 40: [ Species.CRADILY ]}, { 1: [ Species.ANORITH ], 40: [ Species.ARMALDO ]}]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGIROCK, Species.TAPU_BULU, Species.PHEROMOSA ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.HIPPOWDON, Species.HELIOLISK, Species.RABSCA ], [TimeOfDay.DAY]: [ Species.HIPPOWDON, Species.HELIOLISK, Species.RABSCA ], @@ -852,9 +852,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.CACTURNE, Species.KROOKODILE ], [TimeOfDay.ALL]: [ Species.SANDSLASH, Species.DRAPION, Species.DARMANITAN, Species.MARACTUS, Species.SANDACONDA, Species.BRAMBLEGHAST ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CRADILY, Species.ARMALDO ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGIROCK, Species.TAPU_BULU, Species.PHEROMOSA ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CRADILY, Species.ARMALDO ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGIROCK, Species.TAPU_BULU, Species.PHEROMOSA ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.ICE_CAVE]: { [BiomePoolTier.COMMON]: { @@ -863,14 +863,14 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.SEEL ], 34: [ Species.DEWGONG ] }, - { 1: [ Species.SWINUB ], 33: [ Species.PILOSWINE ] }, - { 1: [ Species.SNOVER ], 40: [ Species.ABOMASNOW ] }, - { 1: [ Species.VANILLITE ], 35: [ Species.VANILLISH ], 47: [ Species.VANILLUXE ] }, - { 1: [ Species.CUBCHOO ], 37: [ Species.BEARTIC ] }, - { 1: [ Species.BERGMITE ], 37: [ Species.AVALUGG ] }, + { 1: [ Species.SEEL ], 34: [ Species.DEWGONG ]}, + { 1: [ Species.SWINUB ], 33: [ Species.PILOSWINE ]}, + { 1: [ Species.SNOVER ], 40: [ Species.ABOMASNOW ]}, + { 1: [ Species.VANILLITE ], 35: [ Species.VANILLISH ], 47: [ Species.VANILLUXE ]}, + { 1: [ Species.CUBCHOO ], 37: [ Species.BEARTIC ]}, + { 1: [ Species.BERGMITE ], 37: [ Species.AVALUGG ]}, Species.CRABRAWLER, - { 1: [ Species.SNOM ], 20: [ Species.FROSMOTH ] } + { 1: [ Species.SNOM ], 20: [ Species.FROSMOTH ]} ] }, [BiomePoolTier.UNCOMMON]: { @@ -880,15 +880,15 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SNEASEL, - { 1: [ Species.SNORUNT ], 42: [ Species.GLALIE ] }, - { 1: [ Species.SPHEAL ], 32: [ Species.SEALEO ], 44: [ Species.WALREIN ] }, + { 1: [ Species.SNORUNT ], 42: [ Species.GLALIE ]}, + { 1: [ Species.SPHEAL ], 32: [ Species.SEALEO ], 44: [ Species.WALREIN ]}, Species.EISCUE, - { 1: [ Species.CETODDLE ], 30: [ Species.CETITAN ] } + { 1: [ Species.CETODDLE ], 30: [ Species.CETITAN ]} ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.JYNX, Species.LAPRAS, Species.FROSLASS, Species.CRYOGONAL ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DELIBIRD, Species.ROTOM, { 1: [ Species.AMAURA ], 59: [ Species.AURORUS ] } ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ARTICUNO, Species.REGICE ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.JYNX, Species.LAPRAS, Species.FROSLASS, Species.CRYOGONAL ]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DELIBIRD, Species.ROTOM, { 1: [ Species.AMAURA ], 59: [ Species.AURORUS ]}]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ARTICUNO, Species.REGICE ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], @@ -896,46 +896,46 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DEWGONG, Species.GLALIE, Species.WALREIN, Species.WEAVILE, Species.MAMOSWINE, Species.FROSLASS, Species.VANILLUXE, Species.BEARTIC, Species.CRYOGONAL, Species.AVALUGG, Species.CRABOMINABLE, Species.CETITAN ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.JYNX, Species.LAPRAS, Species.GLACEON, Species.AURORUS ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ARTICUNO, Species.REGICE, Species.ROTOM ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KYUREM ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.JYNX, Species.LAPRAS, Species.GLACEON, Species.AURORUS ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ARTICUNO, Species.REGICE, Species.ROTOM ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KYUREM ]} }, [Biome.MEADOW]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.LEDYBA ], 18: [ Species.LEDIAN ] }, Species.ROSELIA, Species.COTTONEE, Species.MINCCINO ], + [TimeOfDay.DAWN]: [{ 1: [ Species.LEDYBA ], 18: [ Species.LEDIAN ]}, Species.ROSELIA, Species.COTTONEE, Species.MINCCINO ], [TimeOfDay.DAY]: [ Species.ROSELIA, Species.COTTONEE, Species.MINCCINO ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.BLITZLE ], 27: [ Species.ZEBSTRIKA ] }, - { 1: [ Species.FLABEBE ], 19: [ Species.FLOETTE ] }, - { 1: [ Species.CUTIEFLY ], 25: [ Species.RIBOMBEE ] }, - { 1: [ Species.GOSSIFLEUR ], 20: [ Species.ELDEGOSS ] }, - { 1: [ Species.WOOLOO ], 24: [ Species.DUBWOOL ] } + { 1: [ Species.BLITZLE ], 27: [ Species.ZEBSTRIKA ]}, + { 1: [ Species.FLABEBE ], 19: [ Species.FLOETTE ]}, + { 1: [ Species.CUTIEFLY ], 25: [ Species.RIBOMBEE ]}, + { 1: [ Species.GOSSIFLEUR ], 20: [ Species.ELDEGOSS ]}, + { 1: [ Species.WOOLOO ], 24: [ Species.DUBWOOL ]} ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [ - { 1: [ Species.PONYTA ], 40: [ Species.RAPIDASH ] }, - { 1: [ Species.SNUBBULL ], 23: [ Species.GRANBULL ] }, - { 1: [ Species.SKITTY ], 30: [ Species.DELCATTY ] }, + { 1: [ Species.PONYTA ], 40: [ Species.RAPIDASH ]}, + { 1: [ Species.SNUBBULL ], 23: [ Species.GRANBULL ]}, + { 1: [ Species.SKITTY ], 30: [ Species.DELCATTY ]}, Species.BOUFFALANT, - { 1: [ Species.SMOLIV ], 25: [ Species.DOLLIV ], 35: [ Species.ARBOLIVA ] } + { 1: [ Species.SMOLIV ], 25: [ Species.DOLLIV ], 35: [ Species.ARBOLIVA ]} ], [TimeOfDay.DAY]: [ - { 1: [ Species.PONYTA ], 40: [ Species.RAPIDASH ] }, - { 1: [ Species.SNUBBULL ], 23: [ Species.GRANBULL ] }, - { 1: [ Species.SKITTY ], 30: [ Species.DELCATTY ] }, + { 1: [ Species.PONYTA ], 40: [ Species.RAPIDASH ]}, + { 1: [ Species.SNUBBULL ], 23: [ Species.GRANBULL ]}, + { 1: [ Species.SKITTY ], 30: [ Species.DELCATTY ]}, Species.BOUFFALANT, - { 1: [ Species.SMOLIV ], 25: [ Species.DOLLIV ], 35: [ Species.ARBOLIVA ] } + { 1: [ Species.SMOLIV ], 25: [ Species.DOLLIV ], 35: [ Species.ARBOLIVA ]} ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.JIGGLYPUFF ], 30: [ Species.WIGGLYTUFF ] }, - { 1: [ Species.MAREEP ], 15: [ Species.FLAAFFY ], 30: [ Species.AMPHAROS ] }, - { 1: [ Species.RALTS ], 20: [ Species.KIRLIA ], 30: [ Species.GARDEVOIR ] }, - { 1: [ Species.GLAMEOW ], 38: [ Species.PURUGLY ] }, + { 1: [ Species.JIGGLYPUFF ], 30: [ Species.WIGGLYTUFF ]}, + { 1: [ Species.MAREEP ], 15: [ Species.FLAAFFY ], 30: [ Species.AMPHAROS ]}, + { 1: [ Species.RALTS ], 20: [ Species.KIRLIA ], 30: [ Species.GARDEVOIR ]}, + { 1: [ Species.GLAMEOW ], 38: [ Species.PURUGLY ]}, Species.ORICORIO ] }, @@ -944,10 +944,10 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ Species.VOLBEAT, Species.ILLUMISE ], - [TimeOfDay.ALL]: [ Species.TAUROS, Species.EEVEE, Species.MILTANK, Species.SPINDA, { 1: [ Species.APPLIN ], 30: [ Species.DIPPLIN ] }, { 1: [ Species.SPRIGATITO ], 16: [ Species.FLORAGATO ], 36: [ Species.MEOWSCARADA ] } ] + [TimeOfDay.ALL]: [ Species.TAUROS, Species.EEVEE, Species.MILTANK, Species.SPINDA, { 1: [ Species.APPLIN ], 30: [ Species.DIPPLIN ]}, { 1: [ Species.SPRIGATITO ], 16: [ Species.FLORAGATO ], 36: [ Species.MEOWSCARADA ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CHANSEY, Species.SYLVEON ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MELOETTA ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CHANSEY, Species.SYLVEON ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MELOETTA ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.LEDIAN, Species.GRANBULL, Species.DELCATTY, Species.ROSERADE, Species.CINCCINO, Species.BOUFFALANT, Species.ARBOLIVA ], [TimeOfDay.DAY]: [ Species.GRANBULL, Species.DELCATTY, Species.ROSERADE, Species.CINCCINO, Species.BOUFFALANT, Species.ARBOLIVA ], @@ -955,9 +955,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TAUROS, Species.MILTANK, Species.GARDEVOIR, Species.PURUGLY, Species.ZEBSTRIKA, Species.FLORGES, Species.RIBOMBEE, Species.DUBWOOL ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ Species.HISUI_LILLIGANT ], [TimeOfDay.DAY]: [ Species.HISUI_LILLIGANT ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.BLISSEY, Species.SYLVEON, Species.FLAPPLE, Species.APPLETUN, Species.MEOWSCARADA, Species.HYDRAPPLE ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MELOETTA ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SHAYMIN ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ Species.HISUI_LILLIGANT ], [TimeOfDay.DAY]: [ Species.HISUI_LILLIGANT ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.BLISSEY, Species.SYLVEON, Species.FLAPPLE, Species.APPLETUN, Species.MEOWSCARADA, Species.HYDRAPPLE ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MELOETTA ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SHAYMIN ]} }, [Biome.POWER_PLANT]: { [BiomePoolTier.COMMON]: { @@ -967,20 +967,20 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.PIKACHU, - { 1: [ Species.MAGNEMITE ], 30: [ Species.MAGNETON ] }, - { 1: [ Species.VOLTORB ], 30: [ Species.ELECTRODE ] }, - { 1: [ Species.ELECTRIKE ], 26: [ Species.MANECTRIC ] }, - { 1: [ Species.SHINX ], 15: [ Species.LUXIO ], 30: [ Species.LUXRAY ] }, + { 1: [ Species.MAGNEMITE ], 30: [ Species.MAGNETON ]}, + { 1: [ Species.VOLTORB ], 30: [ Species.ELECTRODE ]}, + { 1: [ Species.ELECTRIKE ], 26: [ Species.MANECTRIC ]}, + { 1: [ Species.SHINX ], 15: [ Species.LUXIO ], 30: [ Species.LUXRAY ]}, Species.DEDENNE, - { 1: [ Species.GRUBBIN ], 20: [ Species.CHARJABUG ] }, - { 1: [ Species.PAWMI ], 18: [ Species.PAWMO ], 32: [ Species.PAWMOT ] }, - { 1: [ Species.TADBULB ], 30: [ Species.BELLIBOLT ] } + { 1: [ Species.GRUBBIN ], 20: [ Species.CHARJABUG ]}, + { 1: [ Species.PAWMI ], 18: [ Species.PAWMO ], 32: [ Species.PAWMOT ]}, + { 1: [ Species.TADBULB ], 30: [ Species.BELLIBOLT ]} ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ELECTABUZZ, Species.PLUSLE, Species.MINUN, Species.PACHIRISU, Species.EMOLGA, Species.TOGEDEMARU ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.MAREEP ], 15: [ Species.FLAAFFY ] } ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.JOLTEON, Species.HISUI_VOLTORB ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.RAIKOU, Species.THUNDURUS, Species.XURKITREE, Species.ZERAORA, Species.REGIELEKI ] }, + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ELECTABUZZ, Species.PLUSLE, Species.MINUN, Species.PACHIRISU, Species.EMOLGA, Species.TOGEDEMARU ]}, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.MAREEP ], 15: [ Species.FLAAFFY ]}]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.JOLTEON, Species.HISUI_VOLTORB ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.RAIKOU, Species.THUNDURUS, Species.XURKITREE, Species.ZERAORA, Species.REGIELEKI ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], @@ -988,9 +988,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.RAICHU, Species.MANECTRIC, Species.LUXRAY, Species.MAGNEZONE, Species.ELECTIVIRE, Species.DEDENNE, Species.VIKAVOLT, Species.TOGEDEMARU, Species.PAWMOT, Species.BELLIBOLT ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.JOLTEON, Species.AMPHAROS, Species.HISUI_ELECTRODE ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ZAPDOS, Species.RAIKOU, Species.THUNDURUS, Species.XURKITREE, Species.ZERAORA, Species.REGIELEKI ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ZEKROM ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.JOLTEON, Species.AMPHAROS, Species.HISUI_ELECTRODE ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ZAPDOS, Species.RAIKOU, Species.THUNDURUS, Species.XURKITREE, Species.ZERAORA, Species.REGIELEKI ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ZEKROM ]} }, [Biome.VOLCANO]: { [BiomePoolTier.COMMON]: { @@ -1001,32 +1001,32 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.ALL]: [ Species.VULPIX, Species.GROWLITHE, - { 1: [ Species.PONYTA ], 40: [ Species.RAPIDASH ] }, - { 1: [ Species.SLUGMA ], 38: [ Species.MAGCARGO ] }, - { 1: [ Species.NUMEL ], 33: [ Species.CAMERUPT ] }, - { 1: [ Species.SALANDIT ], 33: [ Species.SALAZZLE ] }, - { 1: [ Species.ROLYCOLY ], 18: [ Species.CARKOL ], 34: [ Species.COALOSSAL ] } + { 1: [ Species.PONYTA ], 40: [ Species.RAPIDASH ]}, + { 1: [ Species.SLUGMA ], 38: [ Species.MAGCARGO ]}, + { 1: [ Species.NUMEL ], 33: [ Species.CAMERUPT ]}, + { 1: [ Species.SALANDIT ], 33: [ Species.SALAZZLE ]}, + { 1: [ Species.ROLYCOLY ], 18: [ Species.CARKOL ], 34: [ Species.COALOSSAL ]} ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MAGMAR, Species.TORKOAL, { 1: [ Species.PANSEAR ], 30: [ Species.SIMISEAR ] }, Species.HEATMOR, Species.TURTONATOR ] }, + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MAGMAR, Species.TORKOAL, { 1: [ Species.PANSEAR ], 30: [ Species.SIMISEAR ]}, Species.HEATMOR, Species.TURTONATOR ]}, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.CHARMANDER ], 16: [ Species.CHARMELEON ], 36: [ Species.CHARIZARD ] }, - { 1: [ Species.CYNDAQUIL ], 14: [ Species.QUILAVA ], 36: [ Species.TYPHLOSION ] }, - { 1: [ Species.CHIMCHAR ], 14: [ Species.MONFERNO ], 36: [ Species.INFERNAPE ] }, - { 1: [ Species.TEPIG ], 17: [ Species.PIGNITE ], 36: [ Species.EMBOAR ] }, - { 1: [ Species.FENNEKIN ], 16: [ Species.BRAIXEN ], 36: [ Species.DELPHOX ] }, - { 1: [ Species.LITTEN ], 17: [ Species.TORRACAT ], 34: [ Species.INCINEROAR ] }, - { 1: [ Species.SCORBUNNY ], 16: [ Species.RABOOT ], 35: [ Species.CINDERACE ] }, - { 1: [ Species.CHARCADET ], 30: [ Species.ARMAROUGE ] } + { 1: [ Species.CHARMANDER ], 16: [ Species.CHARMELEON ], 36: [ Species.CHARIZARD ]}, + { 1: [ Species.CYNDAQUIL ], 14: [ Species.QUILAVA ], 36: [ Species.TYPHLOSION ]}, + { 1: [ Species.CHIMCHAR ], 14: [ Species.MONFERNO ], 36: [ Species.INFERNAPE ]}, + { 1: [ Species.TEPIG ], 17: [ Species.PIGNITE ], 36: [ Species.EMBOAR ]}, + { 1: [ Species.FENNEKIN ], 16: [ Species.BRAIXEN ], 36: [ Species.DELPHOX ]}, + { 1: [ Species.LITTEN ], 17: [ Species.TORRACAT ], 34: [ Species.INCINEROAR ]}, + { 1: [ Species.SCORBUNNY ], 16: [ Species.RABOOT ], 35: [ Species.CINDERACE ]}, + { 1: [ Species.CHARCADET ], 30: [ Species.ARMAROUGE ]} ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.FLAREON, Species.ROTOM, { 1: [ Species.LARVESTA ], 59: [ Species.VOLCARONA ] }, Species.HISUI_GROWLITHE ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ENTEI, Species.HEATRAN, Species.VOLCANION, Species.CHI_YU ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.FLAREON, Species.ROTOM, { 1: [ Species.LARVESTA ], 59: [ Species.VOLCARONA ]}, Species.HISUI_GROWLITHE ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ENTEI, Species.HEATRAN, Species.VOLCANION, Species.CHI_YU ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], @@ -1041,8 +1041,8 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CHARIZARD, Species.FLAREON, Species.TYPHLOSION, Species.INFERNAPE, Species.EMBOAR, Species.VOLCARONA, Species.DELPHOX, Species.INCINEROAR, Species.CINDERACE, Species.ARMAROUGE, Species.HISUI_ARCANINE ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MOLTRES, Species.ENTEI, Species.ROTOM, Species.HEATRAN, Species.VOLCANION, Species.CHI_YU ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.RESHIRAM ] } + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MOLTRES, Species.ENTEI, Species.ROTOM, Species.HEATRAN, Species.VOLCANION, Species.CHI_YU ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.RESHIRAM ]} }, [Biome.GRAVEYARD]: { [BiomePoolTier.COMMON]: { @@ -1051,14 +1051,14 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.GASTLY ], 25: [ Species.HAUNTER ] }, - { 1: [ Species.SHUPPET ], 37: [ Species.BANETTE ] }, - { 1: [ Species.DUSKULL ], 37: [ Species.DUSCLOPS ] }, - { 1: [ Species.DRIFLOON ], 28: [ Species.DRIFBLIM ] }, - { 1: [ Species.LITWICK ], 41: [ Species.LAMPENT ] }, + { 1: [ Species.GASTLY ], 25: [ Species.HAUNTER ]}, + { 1: [ Species.SHUPPET ], 37: [ Species.BANETTE ]}, + { 1: [ Species.DUSKULL ], 37: [ Species.DUSCLOPS ]}, + { 1: [ Species.DRIFLOON ], 28: [ Species.DRIFBLIM ]}, + { 1: [ Species.LITWICK ], 41: [ Species.LAMPENT ]}, Species.PHANTUMP, Species.PUMPKABOO, - { 1: [ Species.GREAVARD ], 60: [ Species.HOUNDSTONE ] } + { 1: [ Species.GREAVARD ], 60: [ Species.HOUNDSTONE ]} ] }, [BiomePoolTier.UNCOMMON]: { @@ -1066,11 +1066,11 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ { 1: [ Species.CUBONE ], 28: [ Species.MAROWAK ] }, { 1: [ Species.YAMASK ], 34: [ Species.COFAGRIGUS ] }, { 1: [ Species.SINISTEA ], 30: [ Species.POLTEAGEIST ] } ] + [TimeOfDay.ALL]: [{ 1: [ Species.CUBONE ], 28: [ Species.MAROWAK ]}, { 1: [ Species.YAMASK ], 34: [ Species.COFAGRIGUS ]}, { 1: [ Species.SINISTEA ], 30: [ Species.POLTEAGEIST ]}] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MISDREAVUS, Species.MIMIKYU, { 1: [ Species.FUECOCO ], 16: [ Species.CROCALOR ], 36: [ Species.SKELEDIRGE ] }, Species.CERULEDGE ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SPIRITOMB ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MARSHADOW, Species.SPECTRIER ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MISDREAVUS, Species.MIMIKYU, { 1: [ Species.FUECOCO ], 16: [ Species.CROCALOR ], 36: [ Species.SKELEDIRGE ]}, Species.CERULEDGE ]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SPIRITOMB ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MARSHADOW, Species.SPECTRIER ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.MAROWAK ], [TimeOfDay.DAY]: [ Species.MAROWAK ], @@ -1078,9 +1078,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GENGAR, Species.BANETTE, Species.DRIFBLIM, Species.MISMAGIUS, Species.DUSKNOIR, Species.CHANDELURE, Species.TREVENANT, Species.GOURGEIST, Species.MIMIKYU, Species.POLTEAGEIST, Species.HOUNDSTONE ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SKELEDIRGE, Species.CERULEDGE, Species.HISUI_TYPHLOSION ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MARSHADOW, Species.SPECTRIER ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GIRATINA ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.SKELEDIRGE, Species.CERULEDGE, Species.HISUI_TYPHLOSION ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MARSHADOW, Species.SPECTRIER ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GIRATINA ]} }, [Biome.DOJO]: { [BiomePoolTier.COMMON]: { @@ -1089,11 +1089,11 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.MANKEY ], 28: [ Species.PRIMEAPE ], 75: [ Species.ANNIHILAPE ] }, - { 1: [ Species.MAKUHITA ], 24: [ Species.HARIYAMA ] }, - { 1: [ Species.MEDITITE ], 37: [ Species.MEDICHAM ] }, - { 1: [ Species.STUFFUL ], 27: [ Species.BEWEAR ] }, - { 1: [ Species.CLOBBOPUS ], 55: [ Species.GRAPPLOCT ] } + { 1: [ Species.MANKEY ], 28: [ Species.PRIMEAPE ], 75: [ Species.ANNIHILAPE ]}, + { 1: [ Species.MAKUHITA ], 24: [ Species.HARIYAMA ]}, + { 1: [ Species.MEDITITE ], 37: [ Species.MEDICHAM ]}, + { 1: [ Species.STUFFUL ], 27: [ Species.BEWEAR ]}, + { 1: [ Species.CLOBBOPUS ], 55: [ Species.GRAPPLOCT ]} ] }, [BiomePoolTier.UNCOMMON]: { @@ -1101,11 +1101,11 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ { 1: [ Species.CROAGUNK ], 37: [ Species.TOXICROAK ] }, { 1: [ Species.SCRAGGY ], 39: [ Species.SCRAFTY ] }, { 1: [ Species.MIENFOO ], 50: [ Species.MIENSHAO ] } ] + [TimeOfDay.ALL]: [{ 1: [ Species.CROAGUNK ], 37: [ Species.TOXICROAK ]}, { 1: [ Species.SCRAGGY ], 39: [ Species.SCRAFTY ]}, { 1: [ Species.MIENFOO ], 50: [ Species.MIENSHAO ]}] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HITMONLEE, Species.HITMONCHAN, Species.LUCARIO, Species.THROH, Species.SAWK, { 1: [ Species.PANCHAM ], 52: [ Species.PANGORO ] } ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HITMONTOP, Species.GALLADE, Species.GALAR_FARFETCHD ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TERRAKION, Species.KUBFU, Species.GALAR_ZAPDOS ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HITMONLEE, Species.HITMONCHAN, Species.LUCARIO, Species.THROH, Species.SAWK, { 1: [ Species.PANCHAM ], 52: [ Species.PANGORO ]}]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HITMONTOP, Species.GALLADE, Species.GALAR_FARFETCHD ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TERRAKION, Species.KUBFU, Species.GALAR_ZAPDOS ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], @@ -1113,9 +1113,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HITMONLEE, Species.HITMONCHAN, Species.HARIYAMA, Species.MEDICHAM, Species.LUCARIO, Species.TOXICROAK, Species.THROH, Species.SAWK, Species.SCRAFTY, Species.MIENSHAO, Species.BEWEAR, Species.GRAPPLOCT, Species.ANNIHILAPE ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HITMONTOP, Species.GALLADE, Species.PANGORO, Species.SIRFETCHD, Species.HISUI_DECIDUEYE ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TERRAKION, Species.URSHIFU ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ZAMAZENTA, Species.GALAR_ZAPDOS ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HITMONTOP, Species.GALLADE, Species.PANGORO, Species.SIRFETCHD, Species.HISUI_DECIDUEYE ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TERRAKION, Species.URSHIFU ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ZAMAZENTA, Species.GALAR_ZAPDOS ]} }, [Biome.FACTORY]: { [BiomePoolTier.COMMON]: { @@ -1124,21 +1124,21 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.MACHOP ], 28: [ Species.MACHOKE ] }, - { 1: [ Species.MAGNEMITE ], 30: [ Species.MAGNETON ] }, - { 1: [ Species.VOLTORB ], 30: [ Species.ELECTRODE ] }, - { 1: [ Species.TIMBURR ], 25: [ Species.GURDURR ] }, - { 1: [ Species.KLINK ], 38: [ Species.KLANG ], 49: [ Species.KLINKLANG ] } + { 1: [ Species.MACHOP ], 28: [ Species.MACHOKE ]}, + { 1: [ Species.MAGNEMITE ], 30: [ Species.MAGNETON ]}, + { 1: [ Species.VOLTORB ], 30: [ Species.ELECTRODE ]}, + { 1: [ Species.TIMBURR ], 25: [ Species.GURDURR ]}, + { 1: [ Species.KLINK ], 38: [ Species.KLANG ], 49: [ Species.KLINKLANG ]} ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.BRONZOR ], 33: [ Species.BRONZONG ] }, Species.KLEFKI ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ] } ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.BELDUM ], 20: [ Species.METANG ], 45: [ Species.METAGROSS ] } ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GENESECT, Species.MAGEARNA ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KLINKLANG, Species.KLEFKI ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GENESECT, Species.MAGEARNA ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.BRONZOR ], 33: [ Species.BRONZONG ]}, Species.KLEFKI ]}, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ]}]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.BELDUM ], 20: [ Species.METANG ], 45: [ Species.METAGROSS ]}]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GENESECT, Species.MAGEARNA ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KLINKLANG, Species.KLEFKI ]}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GENESECT, Species.MAGEARNA ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.RUINS]: { [BiomePoolTier.COMMON]: { @@ -1147,12 +1147,12 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.DROWZEE ], 26: [ Species.HYPNO ] }, - { 1: [ Species.NATU ], 25: [ Species.XATU ] }, + { 1: [ Species.DROWZEE ], 26: [ Species.HYPNO ]}, + { 1: [ Species.NATU ], 25: [ Species.XATU ]}, Species.UNOWN, - { 1: [ Species.SPOINK ], 32: [ Species.GRUMPIG ] }, - { 1: [ Species.BALTOY ], 36: [ Species.CLAYDOL ] }, - { 1: [ Species.ELGYEM ], 42: [ Species.BEHEEYEM ] } + { 1: [ Species.SPOINK ], 32: [ Species.GRUMPIG ]}, + { 1: [ Species.BALTOY ], 36: [ Species.CLAYDOL ]}, + { 1: [ Species.ELGYEM ], 42: [ Species.BEHEEYEM ]} ] }, [BiomePoolTier.UNCOMMON]: { @@ -1160,58 +1160,58 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ { 1: [ Species.ABRA ], 16: [ Species.KADABRA ] }, Species.SIGILYPH, { 1: [ Species.TINKATINK ], 24: [ Species.TINKATUFF ], 38: [ Species.TINKATON ] } ] + [TimeOfDay.ALL]: [{ 1: [ Species.ABRA ], 16: [ Species.KADABRA ]}, Species.SIGILYPH, { 1: [ Species.TINKATINK ], 24: [ Species.TINKATUFF ], 38: [ Species.TINKATON ]}] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MR_MIME, Species.WOBBUFFET, { 1: [ Species.GOTHITA ], 32: [ Species.GOTHORITA ], 41: [ Species.GOTHITELLE ] }, Species.STONJOURNER ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MR_MIME, Species.WOBBUFFET, { 1: [ Species.GOTHITA ], 32: [ Species.GOTHORITA ], 41: [ Species.GOTHITELLE ]}, Species.STONJOURNER ]}, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ Species.ESPEON ], - [TimeOfDay.DUSK]: [ { 1: [ Species.GALAR_YAMASK ], 34: [ Species.RUNERIGUS ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.GALAR_YAMASK ], 34: [ Species.RUNERIGUS ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.ARCHEN ], 37: [ Species.ARCHEOPS ] } ] + [TimeOfDay.DUSK]: [{ 1: [ Species.GALAR_YAMASK ], 34: [ Species.RUNERIGUS ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.GALAR_YAMASK ], 34: [ Species.RUNERIGUS ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.ARCHEN ], 37: [ Species.ARCHEOPS ]}] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGISTEEL, Species.FEZANDIPITI ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ALAKAZAM, Species.HYPNO, Species.XATU, Species.GRUMPIG, Species.CLAYDOL, Species.SIGILYPH, Species.GOTHITELLE, Species.BEHEEYEM, Species.TINKATON ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ Species.ESPEON ], [TimeOfDay.DUSK]: [ Species.RUNERIGUS ], [TimeOfDay.NIGHT]: [ Species.RUNERIGUS ], [TimeOfDay.ALL]: [ Species.MR_MIME, Species.WOBBUFFET, Species.ARCHEOPS ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGISTEEL, Species.FEZANDIPITI ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KORAIDON ] } + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGISTEEL, Species.FEZANDIPITI ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ALAKAZAM, Species.HYPNO, Species.XATU, Species.GRUMPIG, Species.CLAYDOL, Species.SIGILYPH, Species.GOTHITELLE, Species.BEHEEYEM, Species.TINKATON ]}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ Species.ESPEON ], [TimeOfDay.DUSK]: [ Species.RUNERIGUS ], [TimeOfDay.NIGHT]: [ Species.RUNERIGUS ], [TimeOfDay.ALL]: [ Species.MR_MIME, Species.WOBBUFFET, Species.ARCHEOPS ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGISTEEL, Species.FEZANDIPITI ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KORAIDON ]} }, [Biome.WASTELAND]: { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [ - { 1: [ Species.BAGON ], 30: [ Species.SHELGON ], 50: [ Species.SALAMENCE ] }, - { 1: [ Species.GOOMY ], 40: [ Species.SLIGGOO ], 80: [ Species.GOODRA ] }, - { 1: [ Species.JANGMO_O ], 35: [ Species.HAKAMO_O ], 45: [ Species.KOMMO_O ] } + { 1: [ Species.BAGON ], 30: [ Species.SHELGON ], 50: [ Species.SALAMENCE ]}, + { 1: [ Species.GOOMY ], 40: [ Species.SLIGGOO ], 80: [ Species.GOODRA ]}, + { 1: [ Species.JANGMO_O ], 35: [ Species.HAKAMO_O ], 45: [ Species.KOMMO_O ]} ], [TimeOfDay.DAY]: [ - { 1: [ Species.BAGON ], 30: [ Species.SHELGON ], 50: [ Species.SALAMENCE ] }, - { 1: [ Species.GOOMY ], 40: [ Species.SLIGGOO ], 80: [ Species.GOODRA ] }, - { 1: [ Species.JANGMO_O ], 35: [ Species.HAKAMO_O ], 45: [ Species.KOMMO_O ] } + { 1: [ Species.BAGON ], 30: [ Species.SHELGON ], 50: [ Species.SALAMENCE ]}, + { 1: [ Species.GOOMY ], 40: [ Species.SLIGGOO ], 80: [ Species.GOODRA ]}, + { 1: [ Species.JANGMO_O ], 35: [ Species.HAKAMO_O ], 45: [ Species.KOMMO_O ]} ], - [TimeOfDay.DUSK]: [ { 1: [ Species.LARVITAR ], 30: [ Species.PUPITAR ], 55: [ Species.TYRANITAR ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.LARVITAR ], 30: [ Species.PUPITAR ], 55: [ Species.TYRANITAR ] } ], + [TimeOfDay.DUSK]: [{ 1: [ Species.LARVITAR ], 30: [ Species.PUPITAR ], 55: [ Species.TYRANITAR ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.LARVITAR ], 30: [ Species.PUPITAR ], 55: [ Species.TYRANITAR ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.VIBRAVA ], 45: [ Species.FLYGON ] }, - { 1: [ Species.GIBLE ], 24: [ Species.GABITE ], 48: [ Species.GARCHOMP ] }, - { 1: [ Species.AXEW ], 38: [ Species.FRAXURE ], 48: [ Species.HAXORUS ] } + { 1: [ Species.VIBRAVA ], 45: [ Species.FLYGON ]}, + { 1: [ Species.GIBLE ], 24: [ Species.GABITE ], 48: [ Species.GARCHOMP ]}, + { 1: [ Species.AXEW ], 38: [ Species.FRAXURE ], 48: [ Species.HAXORUS ]} ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ { 1: [ Species.DEINO ], 50: [ Species.ZWEILOUS ], 64: [ Species.HYDREIGON ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.DEINO ], 50: [ Species.ZWEILOUS ], 64: [ Species.HYDREIGON ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.SWABLU ], 35: [ Species.ALTARIA ] }, Species.DRAMPA, Species.CYCLIZAR ] + [TimeOfDay.DUSK]: [{ 1: [ Species.DEINO ], 50: [ Species.ZWEILOUS ], 64: [ Species.HYDREIGON ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.DEINO ], 50: [ Species.ZWEILOUS ], 64: [ Species.HYDREIGON ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.SWABLU ], 35: [ Species.ALTARIA ]}, Species.DRAMPA, Species.CYCLIZAR ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ { 1: [ Species.DREEPY ], 50: [ Species.DRAKLOAK ], 60: [ Species.DRAGAPULT ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.DREEPY ], 50: [ Species.DRAKLOAK ], 60: [ Species.DRAGAPULT ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.DRATINI ], 30: [ Species.DRAGONAIR ], 55: [ Species.DRAGONITE ] }, { 1: [ Species.FRIGIBAX ], 35: [ Species.ARCTIBAX ], 54: [ Species.BAXCALIBUR ] } ] + [TimeOfDay.DUSK]: [{ 1: [ Species.DREEPY ], 50: [ Species.DRAKLOAK ], 60: [ Species.DRAGAPULT ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.DREEPY ], 50: [ Species.DRAKLOAK ], 60: [ Species.DRAGAPULT ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.DRATINI ], 30: [ Species.DRAGONAIR ], 55: [ Species.DRAGONITE ]}, { 1: [ Species.FRIGIBAX ], 35: [ Species.ARCTIBAX ], 54: [ Species.BAXCALIBUR ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.AERODACTYL, Species.DRUDDIGON, { 1: [ Species.TYRUNT ], 59: [ Species.TYRANTRUM ] }, Species.DRACOZOLT, Species.DRACOVISH ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGIDRAGO ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.AERODACTYL, Species.DRUDDIGON, { 1: [ Species.TYRUNT ], 59: [ Species.TYRANTRUM ]}, Species.DRACOZOLT, Species.DRACOVISH ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGIDRAGO ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.SALAMENCE, Species.GOODRA, Species.KOMMO_O ], [TimeOfDay.DAY]: [ Species.SALAMENCE, Species.GOODRA, Species.KOMMO_O ], @@ -1219,9 +1219,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.TYRANITAR, Species.DRAGAPULT ], [TimeOfDay.ALL]: [ Species.DRAGONITE, Species.FLYGON, Species.GARCHOMP, Species.HAXORUS, Species.DRAMPA, Species.BAXCALIBUR ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.AERODACTYL, Species.DRUDDIGON, Species.TYRANTRUM, Species.DRACOZOLT, Species.DRACOVISH ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGIDRAGO ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DIALGA ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.AERODACTYL, Species.DRUDDIGON, Species.TYRANTRUM, Species.DRACOZOLT, Species.DRACOVISH ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGIDRAGO ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DIALGA ]} }, [Biome.ABYSS]: { [BiomePoolTier.COMMON]: { @@ -1231,25 +1231,25 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MURKROW, - { 1: [ Species.HOUNDOUR ], 24: [ Species.HOUNDOOM ] }, + { 1: [ Species.HOUNDOUR ], 24: [ Species.HOUNDOOM ]}, Species.SABLEYE, - { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, - { 1: [ Species.PAWNIARD ], 52: [ Species.BISHARP ], 64: [ Species.KINGAMBIT ] }, - { 1: [ Species.NICKIT ], 18: [ Species.THIEVUL ] }, - { 1: [ Species.IMPIDIMP ], 32: [ Species.MORGREM ], 42: [ Species.GRIMMSNARL ] }, - { 1: [ Species.MASCHIFF ], 30: [ Species.MABOSSTIFF ] } + { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ]}, + { 1: [ Species.PAWNIARD ], 52: [ Species.BISHARP ], 64: [ Species.KINGAMBIT ]}, + { 1: [ Species.NICKIT ], 18: [ Species.THIEVUL ]}, + { 1: [ Species.IMPIDIMP ], 32: [ Species.MORGREM ], 42: [ Species.GRIMMSNARL ]}, + { 1: [ Species.MASCHIFF ], 30: [ Species.MABOSSTIFF ]} ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ Species.ABSOL, Species.SPIRITOMB, { 1: [ Species.ZORUA ], 30: [ Species.ZOROARK ] }, { 1: [ Species.DEINO ], 50: [ Species.ZWEILOUS ], 64: [ Species.HYDREIGON ] } ] + [TimeOfDay.ALL]: [ Species.ABSOL, Species.SPIRITOMB, { 1: [ Species.ZORUA ], 30: [ Species.ZOROARK ]}, { 1: [ Species.DEINO ], 50: [ Species.ZWEILOUS ], 64: [ Species.HYDREIGON ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.UMBREON ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DARKRAI, Species.GALAR_MOLTRES ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.UMBREON ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DARKRAI, Species.GALAR_MOLTRES ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], @@ -1257,9 +1257,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HOUNDOOM, Species.SABLEYE, Species.ABSOL, Species.HONCHKROW, Species.SPIRITOMB, Species.LIEPARD, Species.ZOROARK, Species.HYDREIGON, Species.THIEVUL, Species.GRIMMSNARL, Species.MABOSSTIFF, Species.KINGAMBIT ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.UMBREON, Species.HISUI_SAMUROTT ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DARKRAI ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.PALKIA, Species.YVELTAL, Species.GALAR_MOLTRES ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.UMBREON, Species.HISUI_SAMUROTT ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DARKRAI ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.PALKIA, Species.YVELTAL, Species.GALAR_MOLTRES ]} }, [Biome.SPACE]: { [BiomePoolTier.COMMON]: { @@ -1267,22 +1267,22 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [ Species.SOLROCK ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ Species.LUNATONE ], - [TimeOfDay.ALL]: [ Species.CLEFAIRY, { 1: [ Species.BRONZOR ], 33: [ Species.BRONZONG ] }, { 1: [ Species.MUNNA ], 30: [ Species.MUSHARNA ] }, Species.MINIOR ] + [TimeOfDay.ALL]: [ Species.CLEFAIRY, { 1: [ Species.BRONZOR ], 33: [ Species.BRONZONG ]}, { 1: [ Species.MUNNA ], 30: [ Species.MUSHARNA ]}, Species.MINIOR ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.BALTOY ], 36: [ Species.CLAYDOL ] }, { 1: [ Species.ELGYEM ], 42: [ Species.BEHEEYEM ] } ] }, + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.BALTOY ], 36: [ Species.CLAYDOL ]}, { 1: [ Species.ELGYEM ], 42: [ Species.BEHEEYEM ]}]}, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ { 1: [ Species.BELDUM ], 20: [ Species.METANG ], 45: [ Species.METAGROSS ] }, Species.SIGILYPH, { 1: [ Species.SOLOSIS ], 32: [ Species.DUOSION ], 41: [ Species.REUNICLUS ] } ] + [TimeOfDay.ALL]: [{ 1: [ Species.BELDUM ], 20: [ Species.METANG ], 45: [ Species.METAGROSS ]}, Species.SIGILYPH, { 1: [ Species.SOLOSIS ], 32: [ Species.DUOSION ], 41: [ Species.REUNICLUS ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ] } ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.COSMOG ], 43: [ Species.COSMOEM ] }, Species.CELESTEELA ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ Species.SOLROCK ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ Species.LUNATONE ], [TimeOfDay.ALL]: [ Species.CLEFABLE, Species.BRONZONG, Species.MUSHARNA, Species.REUNICLUS, Species.MINIOR ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.METAGROSS, Species.PORYGON_Z ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CELESTEELA ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ Species.SOLGALEO ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ Species.LUNALA ], [TimeOfDay.ALL]: [ Species.RAYQUAZA, Species.NECROZMA ] } + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ]}]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.COSMOG ], 43: [ Species.COSMOEM ]}, Species.CELESTEELA ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ Species.SOLROCK ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ Species.LUNATONE ], [TimeOfDay.ALL]: [ Species.CLEFABLE, Species.BRONZONG, Species.MUSHARNA, Species.REUNICLUS, Species.MINIOR ]}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.METAGROSS, Species.PORYGON_Z ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CELESTEELA ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ Species.SOLGALEO ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ Species.LUNALA ], [TimeOfDay.ALL]: [ Species.RAYQUAZA, Species.NECROZMA ]} }, [Biome.CONSTRUCTION_SITE]: { [BiomePoolTier.COMMON]: { @@ -1291,10 +1291,10 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.MACHOP ], 28: [ Species.MACHOKE ] }, - { 1: [ Species.MAGNEMITE ], 30: [ Species.MAGNETON ] }, - { 1: [ Species.DRILBUR ], 31: [ Species.EXCADRILL ] }, - { 1: [ Species.TIMBURR ], 25: [ Species.GURDURR ] } + { 1: [ Species.MACHOP ], 28: [ Species.MACHOKE ]}, + { 1: [ Species.MAGNEMITE ], 30: [ Species.MAGNETON ]}, + { 1: [ Species.DRILBUR ], 31: [ Species.EXCADRILL ]}, + { 1: [ Species.TIMBURR ], 25: [ Species.GURDURR ]} ] }, [BiomePoolTier.UNCOMMON]: { @@ -1303,60 +1303,60 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.GRIMER ], 38: [ Species.MUK ] }, - { 1: [ Species.KOFFING ], 35: [ Species.WEEZING ] }, - { 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ] }, - { 1: [ Species.SCRAGGY ], 39: [ Species.SCRAFTY ] } + { 1: [ Species.GRIMER ], 38: [ Species.MUK ]}, + { 1: [ Species.KOFFING ], 35: [ Species.WEEZING ]}, + { 1: [ Species.RHYHORN ], 42: [ Species.RHYDON ]}, + { 1: [ Species.SCRAGGY ], 39: [ Species.SCRAFTY ]} ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ { 1: [ Species.GALAR_MEOWTH ], 28: [ Species.PERRSERKER ] } ], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ONIX, Species.HITMONLEE, Species.HITMONCHAN, Species.DURALUDON ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DITTO, Species.HITMONTOP ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.COBALION, Species.STAKATAKA ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MACHAMP, Species.CONKELDURR ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ Species.PERRSERKER ], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ARCHALUDON ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.COBALION, Species.STAKATAKA ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [{ 1: [ Species.GALAR_MEOWTH ], 28: [ Species.PERRSERKER ]}], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ONIX, Species.HITMONLEE, Species.HITMONCHAN, Species.DURALUDON ]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DITTO, Species.HITMONTOP ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.COBALION, Species.STAKATAKA ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MACHAMP, Species.CONKELDURR ]}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ Species.PERRSERKER ], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ARCHALUDON ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.COBALION, Species.STAKATAKA ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.JUNGLE]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ Species.VESPIQUEN, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ] }, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ] } ], - [TimeOfDay.DAY]: [ Species.VESPIQUEN, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ] }, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ] } ], - [TimeOfDay.DUSK]: [ Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ] }, Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ] }, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] } ], - [TimeOfDay.ALL]: [ Species.AIPOM, { 1: [ Species.BLITZLE ], 27: [ Species.ZEBSTRIKA ] }, { 1: [ Species.PIKIPEK ], 14: [ Species.TRUMBEAK ], 28: [ Species.TOUCANNON ] } ] + [TimeOfDay.DAWN]: [ Species.VESPIQUEN, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ]}, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ]}], + [TimeOfDay.DAY]: [ Species.VESPIQUEN, { 1: [ Species.CHERUBI ], 25: [ Species.CHERRIM ]}, { 1: [ Species.SEWADDLE ], 20: [ Species.SWADLOON ], 30: [ Species.LEAVANNY ]}], + [TimeOfDay.DUSK]: [ Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ]}, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ]}, Species.SHROOMISH, { 1: [ Species.PURRLOIN ], 20: [ Species.LIEPARD ]}, { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ]}], + [TimeOfDay.ALL]: [ Species.AIPOM, { 1: [ Species.BLITZLE ], 27: [ Species.ZEBSTRIKA ]}, { 1: [ Species.PIKIPEK ], 14: [ Species.TRUMBEAK ], 28: [ Species.TOUCANNON ]}] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [ Species.EXEGGCUTE, Species.TROPIUS, Species.COMBEE, Species.KOMALA ], [TimeOfDay.DAY]: [ Species.EXEGGCUTE, Species.TROPIUS, Species.COMBEE, Species.KOMALA ], - [TimeOfDay.DUSK]: [ Species.TANGELA, { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ] }, { 1: [ Species.PANCHAM ], 52: [ Species.PANGORO ] } ], - [TimeOfDay.NIGHT]: [ Species.TANGELA, { 1: [ Species.PANCHAM ], 52: [ Species.PANGORO ] } ], + [TimeOfDay.DUSK]: [ Species.TANGELA, { 1: [ Species.SPINARAK ], 22: [ Species.ARIADOS ]}, { 1: [ Species.PANCHAM ], 52: [ Species.PANGORO ]}], + [TimeOfDay.NIGHT]: [ Species.TANGELA, { 1: [ Species.PANCHAM ], 52: [ Species.PANGORO ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.PANSAGE ], 30: [ Species.SIMISAGE ] }, - { 1: [ Species.PANSEAR ], 30: [ Species.SIMISEAR ] }, - { 1: [ Species.PANPOUR ], 30: [ Species.SIMIPOUR ] }, - { 1: [ Species.JOLTIK ], 36: [ Species.GALVANTULA ] }, - { 1: [ Species.LITLEO ], 35: [ Species.PYROAR ] }, - { 1: [ Species.FOMANTIS ], 44: [ Species.LURANTIS ] }, + { 1: [ Species.PANSAGE ], 30: [ Species.SIMISAGE ]}, + { 1: [ Species.PANSEAR ], 30: [ Species.SIMISEAR ]}, + { 1: [ Species.PANPOUR ], 30: [ Species.SIMIPOUR ]}, + { 1: [ Species.JOLTIK ], 36: [ Species.GALVANTULA ]}, + { 1: [ Species.LITLEO ], 35: [ Species.PYROAR ]}, + { 1: [ Species.FOMANTIS ], 44: [ Species.LURANTIS ]}, Species.FALINKS ] }, [BiomePoolTier.RARE]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] }, Species.PASSIMIAN, { 1: [ Species.GALAR_PONYTA ], 40: [ Species.GALAR_RAPIDASH ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ] }, Species.PASSIMIAN ], + [TimeOfDay.DAWN]: [{ 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ]}, Species.PASSIMIAN, { 1: [ Species.GALAR_PONYTA ], 40: [ Species.GALAR_RAPIDASH ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.FOONGUS ], 39: [ Species.AMOONGUSS ]}, Species.PASSIMIAN ], [TimeOfDay.DUSK]: [ Species.ORANGURU ], [TimeOfDay.NIGHT]: [ Species.ORANGURU ], [TimeOfDay.ALL]: [ Species.SCYTHER, Species.YANMA, - { 1: [ Species.SLAKOTH ], 18: [ Species.VIGOROTH ], 36: [ Species.SLAKING ] }, + { 1: [ Species.SLAKOTH ], 18: [ Species.VIGOROTH ], 36: [ Species.SLAKING ]}, Species.SEVIPER, Species.CARNIVINE, - { 1: [ Species.SNIVY ], 17: [ Species.SERVINE ], 36: [ Species.SERPERIOR ] }, - { 1: [ Species.GROOKEY ], 16: [ Species.THWACKEY ], 35: [ Species.RILLABOOM ] } + { 1: [ Species.SNIVY ], 17: [ Species.SERVINE ], 36: [ Species.SERPERIOR ]}, + { 1: [ Species.GROOKEY ], 16: [ Species.THWACKEY ], 35: [ Species.RILLABOOM ]} ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KANGASKHAN, Species.CHATOT, Species.KLEAVOR ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TAPU_LELE, Species.BUZZWOLE, Species.ZARUDE, Species.MUNKIDORI ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KANGASKHAN, Species.CHATOT, Species.KLEAVOR ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TAPU_LELE, Species.BUZZWOLE, Species.ZARUDE, Species.MUNKIDORI ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.EXEGGUTOR, Species.TROPIUS, Species.CHERRIM, Species.LEAVANNY, Species.KOMALA ], [TimeOfDay.DAY]: [ Species.EXEGGUTOR, Species.TROPIUS, Species.CHERRIM, Species.LEAVANNY, Species.KOMALA ], @@ -1371,8 +1371,8 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KANGASKHAN, Species.SCIZOR, Species.SLAKING, Species.LEAFEON, Species.SERPERIOR, Species.RILLABOOM ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TAPU_LELE, Species.BUZZWOLE, Species.ZARUDE, Species.MUNKIDORI ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KLEAVOR ] } + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TAPU_LELE, Species.BUZZWOLE, Species.ZARUDE, Species.MUNKIDORI ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.KLEAVOR ]} }, [Biome.FAIRY_CAVE]: { [BiomePoolTier.COMMON]: { @@ -1381,14 +1381,14 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.JIGGLYPUFF ], 30: [ Species.WIGGLYTUFF ] }, - { 1: [ Species.MARILL ], 18: [ Species.AZUMARILL ] }, + { 1: [ Species.JIGGLYPUFF ], 30: [ Species.WIGGLYTUFF ]}, + { 1: [ Species.MARILL ], 18: [ Species.AZUMARILL ]}, Species.MAWILE, - { 1: [ Species.SPRITZEE ], 40: [ Species.AROMATISSE ] }, - { 1: [ Species.SWIRLIX ], 40: [ Species.SLURPUFF ] }, - { 1: [ Species.CUTIEFLY ], 25: [ Species.RIBOMBEE ] }, - { 1: [ Species.MORELULL ], 24: [ Species.SHIINOTIC ] }, - { 1: [ Species.MILCERY ], 30: [ Species.ALCREMIE ] } + { 1: [ Species.SPRITZEE ], 40: [ Species.AROMATISSE ]}, + { 1: [ Species.SWIRLIX ], 40: [ Species.SLURPUFF ]}, + { 1: [ Species.CUTIEFLY ], 25: [ Species.RIBOMBEE ]}, + { 1: [ Species.MORELULL ], 24: [ Species.SHIINOTIC ]}, + { 1: [ Species.MILCERY ], 30: [ Species.ALCREMIE ]} ] }, [BiomePoolTier.UNCOMMON]: { @@ -1399,15 +1399,15 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.ALL]: [ Species.CLEFAIRY, Species.TOGETIC, - { 1: [ Species.RALTS ], 20: [ Species.KIRLIA ], 30: [ Species.GARDEVOIR ] }, + { 1: [ Species.RALTS ], 20: [ Species.KIRLIA ], 30: [ Species.GARDEVOIR ]}, Species.CARBINK, Species.COMFEY, - { 1: [ Species.HATENNA ], 32: [ Species.HATTREM ], 42: [ Species.HATTERENE ] } + { 1: [ Species.HATENNA ], 32: [ Species.HATTREM ], 42: [ Species.HATTERENE ]} ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.AUDINO, Species.ETERNAL_FLOETTE ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DIANCIE, Species.ENAMORUS ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.AUDINO, Species.ETERNAL_FLOETTE ]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DIANCIE, Species.ENAMORUS ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], @@ -1415,9 +1415,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.WIGGLYTUFF, Species.MAWILE, Species.TOGEKISS, Species.AUDINO, Species.AROMATISSE, Species.SLURPUFF, Species.CARBINK, Species.RIBOMBEE, Species.SHIINOTIC, Species.COMFEY, Species.HATTERENE, Species.ALCREMIE ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ETERNAL_FLOETTE ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DIANCIE, Species.ENAMORUS ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.XERNEAS ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ETERNAL_FLOETTE ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DIANCIE, Species.ENAMORUS ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.XERNEAS ]} }, [Biome.TEMPLE]: { [BiomePoolTier.COMMON]: { @@ -1426,12 +1426,12 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.GASTLY ], 25: [ Species.HAUNTER ] }, - { 1: [ Species.NATU ], 25: [ Species.XATU ] }, - { 1: [ Species.DUSKULL ], 37: [ Species.DUSCLOPS ] }, - { 1: [ Species.YAMASK ], 34: [ Species.COFAGRIGUS ] }, - { 1: [ Species.GOLETT ], 43: [ Species.GOLURK ] }, - { 1: [ Species.HONEDGE ], 35: [ Species.DOUBLADE ] } + { 1: [ Species.GASTLY ], 25: [ Species.HAUNTER ]}, + { 1: [ Species.NATU ], 25: [ Species.XATU ]}, + { 1: [ Species.DUSKULL ], 37: [ Species.DUSCLOPS ]}, + { 1: [ Species.YAMASK ], 34: [ Species.COFAGRIGUS ]}, + { 1: [ Species.GOLETT ], 43: [ Species.GOLURK ]}, + { 1: [ Species.HONEDGE ], 35: [ Species.DOUBLADE ]} ] }, [BiomePoolTier.UNCOMMON]: { @@ -1440,86 +1440,86 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.CUBONE ], 28: [ Species.MAROWAK ] }, - { 1: [ Species.BALTOY ], 36: [ Species.CLAYDOL ] }, - { 1: [ Species.CHINGLING ], 20: [ Species.CHIMECHO ] }, - { 1: [ Species.SKORUPI ], 40: [ Species.DRAPION ] }, - { 1: [ Species.LITWICK ], 41: [ Species.LAMPENT ] } + { 1: [ Species.CUBONE ], 28: [ Species.MAROWAK ]}, + { 1: [ Species.BALTOY ], 36: [ Species.CLAYDOL ]}, + { 1: [ Species.CHINGLING ], 20: [ Species.CHIMECHO ]}, + { 1: [ Species.SKORUPI ], 40: [ Species.DRAPION ]}, + { 1: [ Species.LITWICK ], 41: [ Species.LAMPENT ]} ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.GIMMIGHOUL ], 40: [ Species.GHOLDENGO ] } ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HOOPA, Species.TAPU_KOKO ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CHIMECHO, Species.COFAGRIGUS, Species.GOLURK, Species.AEGISLASH ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GHOLDENGO ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HOOPA, Species.TAPU_KOKO ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGIGIGAS ] } + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.GIMMIGHOUL ], 40: [ Species.GHOLDENGO ]}]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HOOPA, Species.TAPU_KOKO ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.CHIMECHO, Species.COFAGRIGUS, Species.GOLURK, Species.AEGISLASH ]}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GHOLDENGO ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.HOOPA, Species.TAPU_KOKO ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.REGIGIGAS ]} }, [Biome.SLUM]: { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ { 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ] } ], + [TimeOfDay.DUSK]: [{ 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.PATRAT ], 20: [ Species.WATCHOG ]}], [TimeOfDay.ALL]: [ - { 1: [ Species.RATTATA ], 20: [ Species.RATICATE ] }, - { 1: [ Species.GRIMER ], 38: [ Species.MUK ] }, - { 1: [ Species.KOFFING ], 35: [ Species.WEEZING ] }, - { 1: [ Species.TRUBBISH ], 36: [ Species.GARBODOR ] } + { 1: [ Species.RATTATA ], 20: [ Species.RATICATE ]}, + { 1: [ Species.GRIMER ], 38: [ Species.MUK ]}, + { 1: [ Species.KOFFING ], 35: [ Species.WEEZING ]}, + { 1: [ Species.TRUBBISH ], 36: [ Species.GARBODOR ]} ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ { 1: [ Species.STUNKY ], 34: [ Species.SKUNTANK ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.STUNKY ], 34: [ Species.SKUNTANK ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.BURMY ], 20: [ Species.WORMADAM ] } ] + [TimeOfDay.DUSK]: [{ 1: [ Species.STUNKY ], 34: [ Species.SKUNTANK ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.STUNKY ], 34: [ Species.SKUNTANK ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.BURMY ], 20: [ Species.WORMADAM ]}] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ Species.TOXTRICITY, { 1: [ Species.GALAR_LINOONE ], 65: [ Species.OBSTAGOON ] }, Species.GALAR_ZIGZAGOON ], - [TimeOfDay.NIGHT]: [ Species.TOXTRICITY, { 1: [ Species.GALAR_LINOONE ], 65: [ Species.OBSTAGOON ] }, Species.GALAR_ZIGZAGOON ], - [TimeOfDay.ALL]: [ { 1: [ Species.VAROOM ], 40: [ Species.REVAVROOM ] } ] + [TimeOfDay.DUSK]: [ Species.TOXTRICITY, { 1: [ Species.GALAR_LINOONE ], 65: [ Species.OBSTAGOON ]}, Species.GALAR_ZIGZAGOON ], + [TimeOfDay.NIGHT]: [ Species.TOXTRICITY, { 1: [ Species.GALAR_LINOONE ], 65: [ Species.OBSTAGOON ]}, Species.GALAR_ZIGZAGOON ], + [TimeOfDay.ALL]: [{ 1: [ Species.VAROOM ], 40: [ Species.REVAVROOM ]}] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GUZZLORD ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ Species.SKUNTANK, Species.WATCHOG ], [TimeOfDay.NIGHT]: [ Species.SKUNTANK, Species.WATCHOG ], [TimeOfDay.ALL]: [ Species.MUK, Species.WEEZING, Species.WORMADAM, Species.GARBODOR ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ Species.TOXTRICITY, Species.OBSTAGOON ], [TimeOfDay.NIGHT]: [ Species.TOXTRICITY, Species.OBSTAGOON ], [TimeOfDay.ALL]: [ Species.REVAVROOM, Species.GALAR_WEEZING ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GUZZLORD ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GUZZLORD ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ Species.SKUNTANK, Species.WATCHOG ], [TimeOfDay.NIGHT]: [ Species.SKUNTANK, Species.WATCHOG ], [TimeOfDay.ALL]: [ Species.MUK, Species.WEEZING, Species.WORMADAM, Species.GARBODOR ]}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ Species.TOXTRICITY, Species.OBSTAGOON ], [TimeOfDay.NIGHT]: [ Species.TOXTRICITY, Species.OBSTAGOON ], [TimeOfDay.ALL]: [ Species.REVAVROOM, Species.GALAR_WEEZING ]}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GUZZLORD ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.SNOWY_FOREST]: { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ Species.SNEASEL, { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ] }, { 1: [ Species.SNOM ], 20: [ Species.FROSMOTH ] } ], - [TimeOfDay.NIGHT]: [ Species.SNEASEL, { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ] }, { 1: [ Species.SNOM ], 20: [ Species.FROSMOTH ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.SWINUB ], 33: [ Species.PILOSWINE ] }, { 1: [ Species.SNOVER ], 40: [ Species.ABOMASNOW ] }, Species.EISCUE ] + [TimeOfDay.DUSK]: [ Species.SNEASEL, { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ]}, { 1: [ Species.SNOM ], 20: [ Species.FROSMOTH ]}], + [TimeOfDay.NIGHT]: [ Species.SNEASEL, { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ]}, { 1: [ Species.SNOM ], 20: [ Species.FROSMOTH ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.SWINUB ], 33: [ Species.PILOSWINE ]}, { 1: [ Species.SNOVER ], 40: [ Species.ABOMASNOW ]}, Species.EISCUE ] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ Species.SNEASEL, { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ] }, Species.STANTLER ], - [TimeOfDay.DAY]: [ Species.SNEASEL, { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ] }, Species.STANTLER ], + [TimeOfDay.DAWN]: [ Species.SNEASEL, { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ]}, Species.STANTLER ], + [TimeOfDay.DAY]: [ Species.SNEASEL, { 1: [ Species.TEDDIURSA ], 30: [ Species.URSARING ]}, Species.STANTLER ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.RARE]: { - [TimeOfDay.DAWN]: [ { 1: [ Species.GALAR_DARUMAKA ], 30: [ Species.GALAR_DARMANITAN ] } ], - [TimeOfDay.DAY]: [ { 1: [ Species.GALAR_DARUMAKA ], 30: [ Species.GALAR_DARMANITAN ] } ], + [TimeOfDay.DAWN]: [{ 1: [ Species.GALAR_DARUMAKA ], 30: [ Species.GALAR_DARMANITAN ]}], + [TimeOfDay.DAY]: [{ 1: [ Species.GALAR_DARUMAKA ], 30: [ Species.GALAR_DARMANITAN ]}], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ Species.DELIBIRD, { 1: [ Species.ALOLA_SANDSHREW ], 30: [ Species.ALOLA_SANDSLASH ] }, { 1: [ Species.ALOLA_VULPIX ], 30: [ Species.ALOLA_NINETALES ] } ] + [TimeOfDay.ALL]: [ Species.DELIBIRD, { 1: [ Species.ALOLA_SANDSHREW ], 30: [ Species.ALOLA_SANDSLASH ]}, { 1: [ Species.ALOLA_VULPIX ], 30: [ Species.ALOLA_NINETALES ]}] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [ Species.HISUI_SNEASEL ], [TimeOfDay.DAY]: [ Species.HISUI_SNEASEL ], - [TimeOfDay.DUSK]: [ { 1: [ Species.HISUI_ZORUA ], 30: [ Species.HISUI_ZOROARK ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.HISUI_ZORUA ], 30: [ Species.HISUI_ZOROARK ] } ], - [TimeOfDay.ALL]: [ { 1: [ Species.GALAR_MR_MIME ], 42: [ Species.MR_RIME ] }, Species.ARCTOZOLT, Species.HISUI_AVALUGG ] + [TimeOfDay.DUSK]: [{ 1: [ Species.HISUI_ZORUA ], 30: [ Species.HISUI_ZOROARK ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.HISUI_ZORUA ], 30: [ Species.HISUI_ZOROARK ]}], + [TimeOfDay.ALL]: [{ 1: [ Species.GALAR_MR_MIME ], 42: [ Species.MR_RIME ]}, Species.ARCTOZOLT, Species.HISUI_AVALUGG ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GLASTRIER, Species.CHIEN_PAO, Species.GALAR_ARTICUNO ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.WYRDEER ], [TimeOfDay.DAY]: [ Species.WYRDEER ], [TimeOfDay.DUSK]: [ Species.FROSMOTH ], [TimeOfDay.NIGHT]: [ Species.FROSMOTH ], [TimeOfDay.ALL]: [ Species.ABOMASNOW, Species.URSALUNA ] }, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GLASTRIER, Species.CHIEN_PAO, Species.GALAR_ARTICUNO ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.WYRDEER ], [TimeOfDay.DAY]: [ Species.WYRDEER ], [TimeOfDay.DUSK]: [ Species.FROSMOTH ], [TimeOfDay.NIGHT]: [ Species.FROSMOTH ], [TimeOfDay.ALL]: [ Species.ABOMASNOW, Species.URSALUNA ]}, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ Species.SNEASLER, Species.GALAR_DARMANITAN ], [TimeOfDay.DAY]: [ Species.SNEASLER, Species.GALAR_DARMANITAN ], @@ -1527,22 +1527,22 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.HISUI_ZOROARK ], [TimeOfDay.ALL]: [ Species.MR_RIME, Species.ARCTOZOLT, Species.ALOLA_SANDSLASH, Species.ALOLA_NINETALES ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GLASTRIER, Species.CHIEN_PAO ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ZACIAN, Species.GALAR_ARTICUNO ] } + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.GLASTRIER, Species.CHIEN_PAO ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ZACIAN, Species.GALAR_ARTICUNO ]} }, [Biome.ISLAND]: { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ { 1: [ Species.ALOLA_RATTATA ], 30: [ Species.ALOLA_RATICATE ] }, { 1: [ Species.ALOLA_MEOWTH ], 30: [ Species.ALOLA_PERSIAN ] } ], - [TimeOfDay.NIGHT]: [ { 1: [ Species.ALOLA_RATTATA ], 30: [ Species.ALOLA_RATICATE ] }, { 1: [ Species.ALOLA_MEOWTH ], 30: [ Species.ALOLA_PERSIAN ] } ], + [TimeOfDay.DUSK]: [{ 1: [ Species.ALOLA_RATTATA ], 30: [ Species.ALOLA_RATICATE ]}, { 1: [ Species.ALOLA_MEOWTH ], 30: [ Species.ALOLA_PERSIAN ]}], + [TimeOfDay.NIGHT]: [{ 1: [ Species.ALOLA_RATTATA ], 30: [ Species.ALOLA_RATICATE ]}, { 1: [ Species.ALOLA_MEOWTH ], 30: [ Species.ALOLA_PERSIAN ]}], [TimeOfDay.ALL]: [ Species.ORICORIO, - { 1: [ Species.ALOLA_SANDSHREW ], 30: [ Species.ALOLA_SANDSLASH ] }, - { 1: [ Species.ALOLA_VULPIX ], 30: [ Species.ALOLA_NINETALES ] }, - { 1: [ Species.ALOLA_DIGLETT ], 26: [ Species.ALOLA_DUGTRIO ] }, - { 1: [ Species.ALOLA_GEODUDE ], 25: [ Species.ALOLA_GRAVELER ], 40: [ Species.ALOLA_GOLEM ] }, - { 1: [ Species.ALOLA_GRIMER ], 38: [ Species.ALOLA_MUK ] } + { 1: [ Species.ALOLA_SANDSHREW ], 30: [ Species.ALOLA_SANDSLASH ]}, + { 1: [ Species.ALOLA_VULPIX ], 30: [ Species.ALOLA_NINETALES ]}, + { 1: [ Species.ALOLA_DIGLETT ], 26: [ Species.ALOLA_DUGTRIO ]}, + { 1: [ Species.ALOLA_GEODUDE ], 25: [ Species.ALOLA_GRAVELER ], 40: [ Species.ALOLA_GOLEM ]}, + { 1: [ Species.ALOLA_GRIMER ], 38: [ Species.ALOLA_MUK ]} ] }, [BiomePoolTier.UNCOMMON]: { @@ -1552,9 +1552,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.ALOLA_MAROWAK ], [TimeOfDay.ALL]: [ Species.BRUXISH ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.BLACEPHALON ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.BLACEPHALON ]}, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ Species.ALOLA_RAICHU, Species.ALOLA_EXEGGUTOR ], [TimeOfDay.DAY]: [ Species.ALOLA_RAICHU, Species.ALOLA_EXEGGUTOR ], @@ -1562,9 +1562,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ Species.ALOLA_RATICATE, Species.ALOLA_PERSIAN, Species.ALOLA_MAROWAK ], [TimeOfDay.ALL]: [ Species.ORICORIO, Species.BRUXISH, Species.ALOLA_SANDSLASH, Species.ALOLA_NINETALES, Species.ALOLA_DUGTRIO, Species.ALOLA_GOLEM, Species.ALOLA_MUK ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.BLACEPHALON ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.BLACEPHALON ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} }, [Biome.LABORATORY]: { [BiomePoolTier.COMMON]: { @@ -1573,21 +1573,21 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - { 1: [ Species.MAGNEMITE ], 30: [ Species.MAGNETON ] }, - { 1: [ Species.GRIMER ], 38: [ Species.MUK ] }, - { 1: [ Species.VOLTORB ], 30: [ Species.ELECTRODE ] }, - { 1: [ Species.BRONZOR ], 33: [ Species.BRONZONG ] }, - { 1: [ Species.KLINK ], 38: [ Species.KLANG ], 49: [ Species.KLINKLANG ] } + { 1: [ Species.MAGNEMITE ], 30: [ Species.MAGNETON ]}, + { 1: [ Species.GRIMER ], 38: [ Species.MUK ]}, + { 1: [ Species.VOLTORB ], 30: [ Species.ELECTRODE ]}, + { 1: [ Species.BRONZOR ], 33: [ Species.BRONZONG ]}, + { 1: [ Species.KLINK ], 38: [ Species.KLANG ], 49: [ Species.KLINKLANG ]} ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ { 1: [ Species.SOLOSIS ], 32: [ Species.DUOSION ], 41: [ Species.REUNICLUS ] } ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DITTO, { 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ] } ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROTOM ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TYPE_NULL ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MUK, Species.ELECTRODE, Species.BRONZONG, Species.MAGNEZONE, Species.PORYGON_Z, Species.REUNICLUS, Species.KLINKLANG ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROTOM, Species.ZYGARDE, Species.SILVALLY ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MEWTWO, Species.MIRAIDON ] } + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [{ 1: [ Species.SOLOSIS ], 32: [ Species.DUOSION ], 41: [ Species.REUNICLUS ]}]}, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.DITTO, { 1: [ Species.PORYGON ], 30: [ Species.PORYGON2 ]}]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROTOM ]}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.TYPE_NULL ]}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MUK, Species.ELECTRODE, Species.BRONZONG, Species.MAGNEZONE, Species.PORYGON_Z, Species.REUNICLUS, Species.KLINKLANG ]}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROTOM, Species.ZYGARDE, Species.SILVALLY ]}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.MEWTWO, Species.MIRAIDON ]} }, [Biome.END]: { [BiomePoolTier.COMMON]: { @@ -1610,14 +1610,14 @@ export const biomePokemonPools: BiomePokemonPools = { Species.IRON_THORNS ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROARING_MOON, Species.IRON_VALIANT ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.WALKING_WAKE, Species.IRON_LEAVES, Species.GOUGING_FIRE, Species.RAGING_BOLT, Species.IRON_BOULDER, Species.IRON_CROWN ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ETERNATUS ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ROARING_MOON, Species.IRON_VALIANT ]}, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.WALKING_WAKE, Species.IRON_LEAVES, Species.GOUGING_FIRE, Species.RAGING_BOLT, Species.IRON_BOULDER, Species.IRON_CROWN ]}, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ Species.ETERNATUS ]}, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []}, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: []} } }; @@ -2051,27 +2051,27 @@ export function initBiomes() { ] ], [ Species.CATERPIE, Type.BUG, -1, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.METAPOD, Type.BUG, -1, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.BUTTERFREE, Type.BUG, Type.FLYING, [ - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.WEEDLE, Type.BUG, Type.POISON, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.KAKUNA, Type.BUG, Type.POISON, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.BEEDRILL, Type.BUG, Type.POISON, [ - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.PIDGEY, Type.NORMAL, Type.FLYING, [ @@ -2115,17 +2115,17 @@ export function initBiomes() { ] ], [ Species.EKANS, Type.POISON, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.FOREST, BiomePoolTier.UNCOMMON ], - [ Biome.SWAMP, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SWAMP, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.ARBOK, Type.POISON, -1, [ [ Biome.FOREST, BiomePoolTier.UNCOMMON ], - [ Biome.SWAMP, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SWAMP, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SWAMP, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SWAMP, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.PIKACHU, Type.ELECTRIC, -1, [ @@ -2215,16 +2215,16 @@ export function initBiomes() { ] ], [ Species.ODDISH, Type.GRASS, Type.POISON, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.GLOOM, Type.GRASS, Type.POISON, [ - [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.VILEPLUME, Type.GRASS, Type.POISON, [ - [ Biome.TALL_GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TALL_GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.PARAS, Type.BUG, Type.GRASS, [ @@ -2261,13 +2261,13 @@ export function initBiomes() { ] ], [ Species.MEOWTH, Type.NORMAL, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.PERSIAN, Type.NORMAL, -1, [ - [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.PSYDUCK, Type.WATER, -1, [ @@ -2282,12 +2282,12 @@ export function initBiomes() { ] ], [ Species.MANKEY, Type.FIGHTING, -1, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.DOJO, BiomePoolTier.COMMON ] ] ], [ Species.PRIMEAPE, Type.FIGHTING, -1, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.DOJO, BiomePoolTier.COMMON ] ] ], @@ -2346,16 +2346,16 @@ export function initBiomes() { ] ], [ Species.BELLSPROUT, Type.GRASS, Type.POISON, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.WEEPINBELL, Type.GRASS, Type.POISON, [ - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.VICTREEBEL, Type.GRASS, Type.POISON, [ - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.TENTACOOL, Type.WATER, Type.POISON, [ @@ -2386,25 +2386,25 @@ export function initBiomes() { ] ], [ Species.PONYTA, Type.FIRE, -1, [ - [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.VOLCANO, BiomePoolTier.COMMON ] ] ], [ Species.RAPIDASH, Type.FIRE, -1, [ - [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.VOLCANO, BiomePoolTier.COMMON ], [ Biome.VOLCANO, BiomePoolTier.BOSS ] ] ], [ Species.SLOWPOKE, Type.WATER, Type.PSYCHIC, [ - [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.LAKE, BiomePoolTier.UNCOMMON ] ] ], [ Species.SLOWBRO, Type.WATER, Type.PSYCHIC, [ - [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.LAKE, BiomePoolTier.UNCOMMON ], [ Biome.LAKE, BiomePoolTier.BOSS ] ] @@ -2429,12 +2429,12 @@ export function initBiomes() { ] ], [ Species.DODUO, Type.NORMAL, Type.FLYING, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.DODRIO, Type.NORMAL, Type.FLYING, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SEEL, Type.WATER, -1, [ @@ -2461,13 +2461,13 @@ export function initBiomes() { ] ], [ Species.SHELLDER, Type.WATER, -1, [ - [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.BEACH, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.BEACH, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.SEABED, BiomePoolTier.UNCOMMON ] ] ], [ Species.CLOYSTER, Type.WATER, Type.ICE, [ - [ Biome.BEACH, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.BEACH, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.GASTLY, Type.GHOST, Type.POISON, [ @@ -2523,12 +2523,12 @@ export function initBiomes() { ] ], [ Species.EXEGGCUTE, Type.GRASS, Type.PSYCHIC, [ - [ Biome.FOREST, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.EXEGGUTOR, Type.GRASS, Type.PSYCHIC, [ - [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.CUBONE, Type.GROUND, -1, [ @@ -2542,7 +2542,7 @@ export function initBiomes() { [ Biome.GRAVEYARD, BiomePoolTier.UNCOMMON ], [ Biome.TEMPLE, BiomePoolTier.UNCOMMON ], [ Biome.BADLANDS, BiomePoolTier.BOSS, TimeOfDay.NIGHT ], - [ Biome.GRAVEYARD, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY, TimeOfDay.DUSK ] ] + [ Biome.GRAVEYARD, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY, TimeOfDay.DUSK ]] ] ], [ Species.HITMONLEE, Type.FIGHTING, -1, [ @@ -2573,15 +2573,15 @@ export function initBiomes() { ] ], [ Species.RHYHORN, Type.GROUND, Type.ROCK, [ - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.BADLANDS, BiomePoolTier.COMMON ], [ Biome.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON ] ] ], [ Species.RHYDON, Type.GROUND, Type.ROCK, [ - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.BADLANDS, BiomePoolTier.COMMON ], [ Biome.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON ] ] @@ -2592,7 +2592,7 @@ export function initBiomes() { ] ], [ Species.TANGELA, Type.GRASS, -1, [ - [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.KANGASKHAN, Type.NORMAL, -1, [ @@ -2620,14 +2620,14 @@ export function initBiomes() { ] ], [ Species.STARYU, Type.WATER, -1, [ - [ Biome.BEACH, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.BEACH, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.STARMIE, Type.WATER, Type.PSYCHIC, [ - [ Biome.BEACH, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.BEACH, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.BEACH, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.BEACH, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.MR_MIME, Type.PSYCHIC, Type.FAIRY, [ @@ -2637,7 +2637,7 @@ export function initBiomes() { ], [ Species.SCYTHER, Type.BUG, Type.FLYING, [ [ Biome.TALL_GRASS, BiomePoolTier.SUPER_RARE ], - [ Biome.FOREST, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.FOREST, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.JUNGLE, BiomePoolTier.RARE ] ] ], @@ -2817,13 +2817,13 @@ export function initBiomes() { ] ], [ Species.SENTRET, Type.NORMAL, -1, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.FURRET, Type.NORMAL, -1, [ - [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.HOOTHOOT, Type.NORMAL, Type.FLYING, [ @@ -2860,7 +2860,7 @@ export function initBiomes() { [ Biome.TALL_GRASS, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT ], [ Biome.FOREST, BiomePoolTier.UNCOMMON, TimeOfDay.DUSK ], [ Biome.FOREST, BiomePoolTier.COMMON, TimeOfDay.NIGHT ], - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, TimeOfDay.DUSK ], [ Biome.JUNGLE, BiomePoolTier.COMMON, TimeOfDay.NIGHT ] ] @@ -2921,17 +2921,17 @@ export function initBiomes() { ] ], [ Species.BELLOSSOM, Type.GRASS, -1, [ - [ Biome.TALL_GRASS, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TALL_GRASS, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.MARILL, Type.WATER, Type.FAIRY, [ - [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.FAIRY_CAVE, BiomePoolTier.COMMON ] ] ], [ Species.AZUMARILL, Type.WATER, Type.FAIRY, [ - [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.LAKE, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.LAKE, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.FAIRY_CAVE, BiomePoolTier.COMMON ] ] ], @@ -2946,16 +2946,16 @@ export function initBiomes() { ] ], [ Species.HOPPIP, Type.GRASS, Type.FLYING, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SKIPLOOM, Type.GRASS, Type.FLYING, [ - [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.JUMPLUFF, Type.GRASS, Type.FLYING, [ - [ Biome.GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.AIPOM, Type.NORMAL, -1, [ @@ -2963,12 +2963,12 @@ export function initBiomes() { ] ], [ Species.SUNKERN, Type.GRASS, -1, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SUNFLORA, Type.GRASS, -1, [ - [ Biome.GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.YANMA, Type.BUG, Type.FLYING, [ @@ -2977,13 +2977,13 @@ export function initBiomes() { ], [ Species.WOOPER, Type.WATER, Type.GROUND, [ [ Biome.LAKE, BiomePoolTier.UNCOMMON ], - [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.QUAGSIRE, Type.WATER, Type.GROUND, [ [ Biome.LAKE, BiomePoolTier.UNCOMMON ], - [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SWAMP, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SWAMP, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.ESPEON, Type.PSYCHIC, -1, [ @@ -3024,12 +3024,12 @@ export function initBiomes() { ] ], [ Species.PINECO, Type.BUG, -1, [ - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.FORRETRESS, Type.BUG, Type.STEEL, [ - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.DUNSPARCE, Type.NORMAL, -1, [ @@ -3045,12 +3045,12 @@ export function initBiomes() { ] ], [ Species.SNUBBULL, Type.FAIRY, -1, [ - [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GRANBULL, Type.FAIRY, -1, [ - [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.QWILFISH, Type.WATER, Type.POISON, [ @@ -3074,23 +3074,23 @@ export function initBiomes() { ], [ Species.SNEASEL, Type.DARK, Type.ICE, [ [ Biome.ICE_CAVE, BiomePoolTier.UNCOMMON ], - [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.TEDDIURSA, Type.NORMAL, -1, [ [ Biome.FOREST, BiomePoolTier.UNCOMMON ], [ Biome.CAVE, BiomePoolTier.COMMON ], - [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.URSARING, Type.NORMAL, -1, [ [ Biome.FOREST, BiomePoolTier.UNCOMMON ], [ Biome.CAVE, BiomePoolTier.COMMON ], [ Biome.CAVE, BiomePoolTier.BOSS ], - [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SLUGMA, Type.FIRE, -1, [ @@ -3160,12 +3160,12 @@ export function initBiomes() { ] ], [ Species.PHANPY, Type.GROUND, -1, [ - [ Biome.BADLANDS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.BADLANDS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.DONPHAN, Type.GROUND, -1, [ - [ Biome.BADLANDS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.BADLANDS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.BADLANDS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.BADLANDS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.PORYGON2, Type.NORMAL, -1, [ @@ -3175,9 +3175,9 @@ export function initBiomes() { ] ], [ Species.STANTLER, Type.NORMAL, -1, [ - [ Biome.FOREST, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.FOREST, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.FOREST, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SMEARGLE, Type.NORMAL, -1, [ @@ -3224,17 +3224,17 @@ export function initBiomes() { ], [ Species.LARVITAR, Type.ROCK, Type.GROUND, [ [ Biome.MOUNTAIN, BiomePoolTier.SUPER_RARE ], - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.PUPITAR, Type.ROCK, Type.GROUND, [ [ Biome.MOUNTAIN, BiomePoolTier.SUPER_RARE ], - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.TYRANITAR, Type.ROCK, Type.DARK, [ - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.WASTELAND, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.WASTELAND, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.LUGIA, Type.PSYCHIC, Type.FLYING, [ @@ -3287,16 +3287,16 @@ export function initBiomes() { ] ], [ Species.POOCHYENA, Type.DARK, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.MIGHTYENA, Type.DARK, -1, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.ZIGZAGOON, Type.NORMAL, -1, [ @@ -3334,52 +3334,52 @@ export function initBiomes() { ] ], [ Species.LOTAD, Type.WATER, Type.GRASS, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.LOMBRE, Type.WATER, Type.GRASS, [ - [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.LUDICOLO, Type.WATER, Type.GRASS, [ - [ Biome.SWAMP, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SWAMP, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SEEDOT, Type.GRASS, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.NUZLEAF, Type.GRASS, Type.DARK, [ - [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.SHIFTRY, Type.GRASS, Type.DARK, [ - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.TAILLOW, Type.NORMAL, Type.FLYING, [ [ Biome.TOWN, BiomePoolTier.COMMON ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SWELLOW, Type.NORMAL, Type.FLYING, [ - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.WINGULL, Type.WATER, Type.FLYING, [ - [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.PELIPPER, Type.WATER, Type.FLYING, [ - [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SEA, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SEA, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.RALTS, Type.PSYCHIC, Type.FAIRY, [ @@ -3410,17 +3410,17 @@ export function initBiomes() { ] ], [ Species.SHROOMISH, Type.GRASS, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.BRELOOM, Type.GRASS, Type.FIGHTING, [ - [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.SLAKOTH, Type.NORMAL, -1, [ @@ -3482,13 +3482,13 @@ export function initBiomes() { ] ], [ Species.SKITTY, Type.NORMAL, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.DELCATTY, Type.NORMAL, -1, [ - [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SABLEYE, Type.DARK, Type.GHOST, [ @@ -3502,18 +3502,18 @@ export function initBiomes() { ] ], [ Species.ARON, Type.STEEL, Type.ROCK, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.LAIRON, Type.STEEL, Type.ROCK, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.AGGRON, Type.STEEL, Type.ROCK, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.MOUNTAIN, BiomePoolTier.BOSS ] ] ], @@ -3552,8 +3552,8 @@ export function initBiomes() { ] ], [ Species.ROSELIA, Type.GRASS, Type.POISON, [ - [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MEADOW, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MEADOW, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GULPIN, Type.POISON, -1, [ @@ -3566,12 +3566,12 @@ export function initBiomes() { ] ], [ Species.CARVANHA, Type.WATER, Type.DARK, [ - [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.SHARPEDO, Type.WATER, Type.DARK, [ - [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SEA, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SEA, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SEA, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.WAILMER, Type.WATER, -1, [ @@ -3617,37 +3617,37 @@ export function initBiomes() { ] ], [ Species.TRAPINCH, Type.GROUND, -1, [ - [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.VIBRAVA, Type.GROUND, Type.DRAGON, [ - [ Biome.DESERT, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.DESERT, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.WASTELAND, BiomePoolTier.COMMON ] ] ], [ Species.FLYGON, Type.GROUND, Type.DRAGON, [ - [ Biome.DESERT, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.DESERT, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.WASTELAND, BiomePoolTier.COMMON ], [ Biome.WASTELAND, BiomePoolTier.BOSS ] ] ], [ Species.CACNEA, Type.GRASS, -1, [ - [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.CACTURNE, Type.GRASS, Type.DARK, [ - [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.DESERT, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.DESERT, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.SWABLU, Type.NORMAL, Type.FLYING, [ - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.WASTELAND, BiomePoolTier.UNCOMMON ] ] ], [ Species.ALTARIA, Type.DRAGON, Type.FLYING, [ - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.WASTELAND, BiomePoolTier.UNCOMMON ] ] ], @@ -3760,8 +3760,8 @@ export function initBiomes() { [ Species.TROPIUS, Type.GRASS, Type.FLYING, [ [ Biome.TALL_GRASS, BiomePoolTier.RARE ], [ Biome.FOREST, BiomePoolTier.RARE ], - [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.CHIMECHO, Type.PSYCHIC, -1, [ @@ -3821,16 +3821,16 @@ export function initBiomes() { ] ], [ Species.BAGON, Type.DRAGON, -1, [ - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SHELGON, Type.DRAGON, -1, [ - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SALAMENCE, Type.DRAGON, Type.FLYING, [ - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.WASTELAND, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.WASTELAND, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.BELDUM, Type.STEEL, Type.PSYCHIC, [ @@ -3930,20 +3930,20 @@ export function initBiomes() { ] ], [ Species.STARLY, Type.NORMAL, Type.FLYING, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.STARAVIA, Type.NORMAL, Type.FLYING, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.STARAPTOR, Type.NORMAL, Type.FLYING, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.BIDOOF, Type.NORMAL, -1, [ @@ -3957,27 +3957,27 @@ export function initBiomes() { ] ], [ Species.KRICKETOT, Type.BUG, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.KRICKETUNE, Type.BUG, -1, [ - [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.TALL_GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.TALL_GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.SHINX, Type.ELECTRIC, -1, [ - [ Biome.PLAINS, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.PLAINS, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.POWER_PLANT, BiomePoolTier.COMMON ] ] ], [ Species.LUXIO, Type.ELECTRIC, -1, [ - [ Biome.PLAINS, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.PLAINS, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.POWER_PLANT, BiomePoolTier.COMMON ] ] ], [ Species.LUXRAY, Type.ELECTRIC, -1, [ - [ Biome.PLAINS, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.PLAINS, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.POWER_PLANT, BiomePoolTier.COMMON ], [ Biome.POWER_PLANT, BiomePoolTier.BOSS ] ] @@ -3985,7 +3985,7 @@ export function initBiomes() { [ Species.BUDEW, Type.GRASS, Type.POISON, [ ] ], [ Species.ROSERADE, Type.GRASS, Type.POISON, [ - [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.CRANIDOS, Type.ROCK, -1, [ @@ -4022,22 +4022,22 @@ export function initBiomes() { ] ], [ Species.MOTHIM, Type.BUG, Type.FLYING, [ - [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.COMBEE, Type.BUG, Type.FLYING, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.VESPIQUEN, Type.BUG, Type.FLYING, [ - [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.PACHIRISU, Type.ELECTRIC, -1, [ @@ -4054,15 +4054,15 @@ export function initBiomes() { ] ], [ Species.CHERUBI, Type.GRASS, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.CHERRIM, Type.GRASS, -1, [ - [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SHELLOS, Type.WATER, -1, [ @@ -4122,12 +4122,12 @@ export function initBiomes() { ] ], [ Species.STUNKY, Type.POISON, Type.DARK, [ - [ Biome.SLUM, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SLUM, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.SKUNTANK, Type.POISON, Type.DARK, [ - [ Biome.SLUM, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SLUM, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SLUM, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SLUM, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.BRONZOR, Type.STEEL, Type.PSYCHIC, [ @@ -4186,12 +4186,12 @@ export function initBiomes() { ] ], [ Species.HIPPOPOTAS, Type.GROUND, -1, [ - [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.HIPPOWDON, Type.GROUND, -1, [ - [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.DESERT, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.DESERT, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SKORUPI, Type.POISON, Type.BUG, [ @@ -4208,12 +4208,12 @@ export function initBiomes() { ] ], [ Species.CROAGUNK, Type.POISON, Type.FIGHTING, [ - [ Biome.SWAMP, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.SWAMP, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.DOJO, BiomePoolTier.UNCOMMON ] ] ], [ Species.TOXICROAK, Type.POISON, Type.FIGHTING, [ - [ Biome.SWAMP, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.SWAMP, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.DOJO, BiomePoolTier.UNCOMMON ], [ Biome.DOJO, BiomePoolTier.BOSS ] ] @@ -4265,7 +4265,7 @@ export function initBiomes() { ] ], [ Species.TANGROWTH, Type.GRASS, -1, [ - [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.ELECTIVIRE, Type.ELECTRIC, -1, [ @@ -4436,18 +4436,18 @@ export function initBiomes() { ] ], [ Species.PATRAT, Type.NORMAL, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.METROPOLIS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SLUM, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.METROPOLIS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SLUM, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.WATCHOG, Type.NORMAL, -1, [ - [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.METROPOLIS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SLUM, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SLUM, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.METROPOLIS, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SLUM, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SLUM, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.LILLIPUP, Type.NORMAL, -1, [ @@ -4465,15 +4465,15 @@ export function initBiomes() { ] ], [ Species.PURRLOIN, Type.DARK, -1, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.ABYSS, BiomePoolTier.COMMON ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.LIEPARD, Type.DARK, -1, [ [ Biome.ABYSS, BiomePoolTier.COMMON ], [ Biome.ABYSS, BiomePoolTier.BOSS ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.PANSAGE, Type.GRASS, -1, [ @@ -4519,20 +4519,20 @@ export function initBiomes() { ] ], [ Species.PIDOVE, Type.NORMAL, Type.FLYING, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.TRANQUILL, Type.NORMAL, Type.FLYING, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.UNFEZANT, Type.NORMAL, Type.FLYING, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.BLITZLE, Type.ELECTRIC, -1, [ @@ -4547,15 +4547,15 @@ export function initBiomes() { ] ], [ Species.ROGGENROLA, Type.ROCK, -1, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.BADLANDS, BiomePoolTier.UNCOMMON ], [ Biome.CAVE, BiomePoolTier.COMMON ] ] ], [ Species.BOLDORE, Type.ROCK, -1, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.BADLANDS, BiomePoolTier.UNCOMMON ], [ Biome.CAVE, BiomePoolTier.COMMON ] ] @@ -4627,52 +4627,52 @@ export function initBiomes() { ] ], [ Species.SEWADDLE, Type.BUG, Type.GRASS, [ - [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SWADLOON, Type.BUG, Type.GRASS, [ - [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.LEAVANNY, Type.BUG, Type.GRASS, [ - [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.VENIPEDE, Type.BUG, Type.POISON, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.WHIRLIPEDE, Type.BUG, Type.POISON, [ - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.SCOLIPEDE, Type.BUG, Type.POISON, [ - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.COTTONEE, Type.GRASS, Type.FAIRY, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MEADOW, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MEADOW, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.WHIMSICOTT, Type.GRASS, Type.FAIRY, [ - [ Biome.GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.PETILIL, Type.GRASS, -1, [ - [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.LILLIGANT, Type.GRASS, -1, [ - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.BASCULIN, Type.WATER, -1, [ @@ -4680,19 +4680,19 @@ export function initBiomes() { ] ], [ Species.SANDILE, Type.GROUND, Type.DARK, [ - [ Biome.DESERT, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.DESERT, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.KROKOROK, Type.GROUND, Type.DARK, [ - [ Biome.DESERT, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.DESERT, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.KROOKODILE, Type.GROUND, Type.DARK, [ - [ Biome.DESERT, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.DESERT, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.DESERT, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.DESERT, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.DARUMAKA, Type.FIRE, -1, [ @@ -4786,12 +4786,12 @@ export function initBiomes() { ] ], [ Species.MINCCINO, Type.NORMAL, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MEADOW, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MEADOW, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.CINCCINO, Type.NORMAL, -1, [ - [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GOTHITA, Type.PSYCHIC, -1, [ @@ -4825,12 +4825,12 @@ export function initBiomes() { ] ], [ Species.DUCKLETT, Type.WATER, Type.FLYING, [ - [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SWANNA, Type.WATER, Type.FLYING, [ - [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.LAKE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.LAKE, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.LAKE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.VANILLITE, Type.ICE, -1, [ @@ -4847,12 +4847,12 @@ export function initBiomes() { ] ], [ Species.DEERLING, Type.NORMAL, Type.GRASS, [ - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SAWSBUCK, Type.NORMAL, Type.GRASS, [ - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.EMOLGA, Type.ELECTRIC, Type.FLYING, [ @@ -4868,17 +4868,17 @@ export function initBiomes() { ] ], [ Species.FOONGUS, Type.GRASS, Type.POISON, [ - [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.JUNGLE, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.JUNGLE, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.AMOONGUSS, Type.GRASS, Type.POISON, [ - [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.JUNGLE, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.JUNGLE, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.GRASS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.JUNGLE, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.JUNGLE, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.FRILLISH, Type.WATER, Type.GHOST, [ @@ -5041,26 +5041,26 @@ export function initBiomes() { ] ], [ Species.BOUFFALANT, Type.NORMAL, -1, [ - [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.RUFFLET, Type.NORMAL, Type.FLYING, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.BRAVIARY, Type.NORMAL, Type.FLYING, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.VULLABY, Type.DARK, Type.FLYING, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.MANDIBUZZ, Type.DARK, Type.FLYING, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.HEATMOR, Type.FIRE, -1, [ @@ -5074,17 +5074,17 @@ export function initBiomes() { ] ], [ Species.DEINO, Type.DARK, Type.DRAGON, [ - [ Biome.WASTELAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.WASTELAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.ABYSS, BiomePoolTier.RARE ] ] ], [ Species.ZWEILOUS, Type.DARK, Type.DRAGON, [ - [ Biome.WASTELAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.WASTELAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.ABYSS, BiomePoolTier.RARE ] ] ], [ Species.HYDREIGON, Type.DARK, Type.DRAGON, [ - [ Biome.WASTELAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.WASTELAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.ABYSS, BiomePoolTier.RARE ], [ Biome.ABYSS, BiomePoolTier.BOSS ] ] @@ -5206,30 +5206,30 @@ export function initBiomes() { [ Species.FLETCHLING, Type.NORMAL, Type.FLYING, [ [ Biome.TOWN, BiomePoolTier.COMMON ], [ Biome.PLAINS, BiomePoolTier.UNCOMMON ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.FLETCHINDER, Type.FIRE, Type.FLYING, [ [ Biome.PLAINS, BiomePoolTier.UNCOMMON ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.TALONFLAME, Type.FIRE, Type.FLYING, [ [ Biome.PLAINS, BiomePoolTier.UNCOMMON ], - [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SCATTERBUG, Type.BUG, -1, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SPEWPA, Type.BUG, -1, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.VIVILLON, Type.BUG, Type.FLYING, [ - [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.LITLEO, Type.FIRE, Type.NORMAL, [ @@ -5264,14 +5264,14 @@ export function initBiomes() { ], [ Species.PANCHAM, Type.FIGHTING, -1, [ [ Biome.DOJO, BiomePoolTier.RARE ], - [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.PANGORO, Type.FIGHTING, Type.DARK, [ [ Biome.DOJO, BiomePoolTier.RARE ], [ Biome.DOJO, BiomePoolTier.BOSS_RARE ], - [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.FURFROU, Type.NORMAL, -1, [ @@ -5280,12 +5280,12 @@ export function initBiomes() { ] ], [ Species.ESPURR, Type.PSYCHIC, -1, [ - [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.MEOWSTIC, Type.PSYCHIC, -1, [ - [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.METROPOLIS, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.METROPOLIS, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.HONEDGE, Type.STEEL, Type.GHOST, [ @@ -5319,12 +5319,12 @@ export function initBiomes() { ] ], [ Species.INKAY, Type.DARK, Type.PSYCHIC, [ - [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.MALAMAR, Type.DARK, Type.PSYCHIC, [ - [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SEA, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SEA, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.BINACLE, Type.ROCK, Type.WATER, [ @@ -5355,11 +5355,11 @@ export function initBiomes() { ] ], [ Species.HELIOPTILE, Type.ELECTRIC, Type.NORMAL, [ - [ Biome.DESERT, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.DESERT, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.HELIOLISK, Type.ELECTRIC, Type.NORMAL, [ - [ Biome.DESERT, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.DESERT, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.TYRUNT, Type.ROCK, Type.DRAGON, [ @@ -5402,16 +5402,16 @@ export function initBiomes() { ] ], [ Species.GOOMY, Type.DRAGON, -1, [ - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SLIGGOO, Type.DRAGON, -1, [ - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GOODRA, Type.DRAGON, -1, [ - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.WASTELAND, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.WASTELAND, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.KLEFKI, Type.STEEL, Type.FAIRY, [ @@ -5533,13 +5533,13 @@ export function initBiomes() { ] ], [ Species.YUNGOOS, Type.NORMAL, -1, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GUMSHOOS, Type.NORMAL, -1, [ - [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GRUBBIN, Type.BUG, -1, [ @@ -5622,12 +5622,12 @@ export function initBiomes() { ] ], [ Species.DEWPIDER, Type.WATER, Type.BUG, [ - [ Biome.LAKE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.LAKE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.ARAQUANID, Type.WATER, Type.BUG, [ - [ Biome.LAKE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.LAKE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.LAKE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.LAKE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.FOMANTIS, Type.GRASS, -1, [ @@ -5670,16 +5670,16 @@ export function initBiomes() { ] ], [ Species.BOUNSWEET, Type.GRASS, -1, [ - [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.STEENEE, Type.GRASS, -1, [ - [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.TSAREENA, Type.GRASS, -1, [ - [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.TALL_GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TALL_GRASS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.TALL_GRASS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.COMFEY, Type.FAIRY, -1, [ @@ -5688,11 +5688,11 @@ export function initBiomes() { ] ], [ Species.ORANGURU, Type.NORMAL, Type.PSYCHIC, [ - [ Biome.JUNGLE, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.JUNGLE, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.PASSIMIAN, Type.FIGHTING, -1, [ - [ Biome.JUNGLE, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.JUNGLE, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.WIMPOD, Type.BUG, Type.WATER, [ @@ -5732,8 +5732,8 @@ export function initBiomes() { ] ], [ Species.KOMALA, Type.NORMAL, -1, [ - [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.JUNGLE, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.JUNGLE, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.TURTONATOR, Type.FIRE, Type.DRAGON, [ @@ -5767,16 +5767,16 @@ export function initBiomes() { ] ], [ Species.JANGMO_O, Type.DRAGON, -1, [ - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.HAKAMO_O, Type.DRAGON, Type.FIGHTING, [ - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.KOMMO_O, Type.DRAGON, Type.FIGHTING, [ - [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.WASTELAND, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.WASTELAND, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.WASTELAND, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.TAPU_KOKO, Type.ELECTRIC, Type.FAIRY, [ @@ -5931,43 +5931,43 @@ export function initBiomes() { ] ], [ Species.SKWOVET, Type.NORMAL, -1, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GREEDENT, Type.NORMAL, -1, [ - [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.PLAINS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.ROOKIDEE, Type.FLYING, -1, [ [ Biome.TOWN, BiomePoolTier.RARE ], [ Biome.PLAINS, BiomePoolTier.RARE ], - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.CORVISQUIRE, Type.FLYING, -1, [ [ Biome.PLAINS, BiomePoolTier.RARE ], - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.CORVIKNIGHT, Type.FLYING, Type.STEEL, [ [ Biome.PLAINS, BiomePoolTier.RARE ], - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.BLIPBUG, Type.BUG, -1, [ - [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.TOWN, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.DOTTLER, Type.BUG, Type.PSYCHIC, [ - [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.ORBEETLE, Type.BUG, Type.PSYCHIC, [ - [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.FOREST, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.NICKIT, Type.DARK, -1, [ @@ -6007,12 +6007,12 @@ export function initBiomes() { ] ], [ Species.YAMPER, Type.ELECTRIC, -1, [ - [ Biome.METROPOLIS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.METROPOLIS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.BOLTUND, Type.ELECTRIC, -1, [ - [ Biome.METROPOLIS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.METROPOLIS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.METROPOLIS, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.METROPOLIS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.ROLYCOLY, Type.ROCK, -1, [ @@ -6050,8 +6050,8 @@ export function initBiomes() { ] ], [ Species.CRAMORANT, Type.FLYING, Type.WATER, [ - [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SEA, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SEA, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.ARROKUDA, Type.WATER, -1, [ @@ -6066,17 +6066,17 @@ export function initBiomes() { [ Species.TOXEL, Type.ELECTRIC, Type.POISON, [ ] ], [ Species.TOXTRICITY, Type.ELECTRIC, Type.POISON, [ - [ Biome.SLUM, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SLUM, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SLUM, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SLUM, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.SIZZLIPEDE, Type.FIRE, Type.BUG, [ - [ Biome.BADLANDS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.BADLANDS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.CENTISKORCH, Type.FIRE, Type.BUG, [ - [ Biome.BADLANDS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.BADLANDS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.BADLANDS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.BADLANDS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.CLOBBOPUS, Type.FIGHTING, -1, [ @@ -6124,8 +6124,8 @@ export function initBiomes() { ] ], [ Species.OBSTAGOON, Type.DARK, Type.NORMAL, [ - [ Biome.SLUM, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SLUM, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SLUM, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SLUM, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.PERRSERKER, Type.STEEL, -1, [ @@ -6148,8 +6148,8 @@ export function initBiomes() { ] ], [ Species.RUNERIGUS, Type.GROUND, Type.GHOST, [ - [ Biome.RUINS, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.RUINS, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.RUINS, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.RUINS, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.MILCERY, Type.FAIRY, -1, [ @@ -6172,13 +6172,13 @@ export function initBiomes() { ], [ Species.SNOM, Type.ICE, Type.BUG, [ [ Biome.ICE_CAVE, BiomePoolTier.COMMON ], - [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.FROSMOTH, Type.ICE, Type.BUG, [ [ Biome.ICE_CAVE, BiomePoolTier.COMMON ], - [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SNOWY_FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SNOWY_FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.STONJOURNER, Type.ROCK, -1, [ @@ -6191,11 +6191,11 @@ export function initBiomes() { ] ], [ Species.INDEEDEE, Type.PSYCHIC, Type.NORMAL, [ - [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.MORPEKO, Type.ELECTRIC, Type.DARK, [ - [ Biome.METROPOLIS, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.METROPOLIS, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.CUFANT, Type.STEEL, -1, [ @@ -6232,16 +6232,16 @@ export function initBiomes() { ] ], [ Species.DREEPY, Type.DRAGON, Type.GHOST, [ - [ Biome.WASTELAND, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.WASTELAND, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.DRAKLOAK, Type.DRAGON, Type.GHOST, [ - [ Biome.WASTELAND, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.WASTELAND, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.DRAGAPULT, Type.DRAGON, Type.GHOST, [ - [ Biome.WASTELAND, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.WASTELAND, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.WASTELAND, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.WASTELAND, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.ZACIAN, Type.FAIRY, -1, [ @@ -6294,7 +6294,7 @@ export function initBiomes() { ] ], [ Species.WYRDEER, Type.NORMAL, Type.PSYCHIC, [ - [ Biome.SNOWY_FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.KLEAVOR, Type.BUG, Type.ROCK, [ @@ -6311,7 +6311,7 @@ export function initBiomes() { ] ], [ Species.SNEASLER, Type.FIGHTING, Type.POISON, [ - [ Biome.SNOWY_FOREST, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.OVERQWIL, Type.DARK, Type.POISON, [ @@ -6394,31 +6394,31 @@ export function initBiomes() { ] ], [ Species.PAWMI, Type.ELECTRIC, -1, [ - [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.TOWN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.POWER_PLANT, BiomePoolTier.COMMON ] ] ], [ Species.PAWMO, Type.ELECTRIC, Type.FIGHTING, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.POWER_PLANT, BiomePoolTier.COMMON ] ] ], [ Species.PAWMOT, Type.ELECTRIC, Type.FIGHTING, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], [ Biome.POWER_PLANT, BiomePoolTier.COMMON ], [ Biome.POWER_PLANT, BiomePoolTier.BOSS ] ] ], [ Species.TANDEMAUS, Type.NORMAL, -1, [ - [ Biome.TOWN, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.METROPOLIS, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.TOWN, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.METROPOLIS, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.MAUSHOLD, Type.NORMAL, -1, [ - [ Biome.METROPOLIS, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.METROPOLIS, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.METROPOLIS, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.METROPOLIS, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.FIDOUGH, Type.FAIRY, -1, [ @@ -6432,16 +6432,16 @@ export function initBiomes() { ] ], [ Species.SMOLIV, Type.GRASS, Type.NORMAL, [ - [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.DOLLIV, Type.GRASS, Type.NORMAL, [ - [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.ARBOLIVA, Type.GRASS, Type.NORMAL, [ - [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MEADOW, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MEADOW, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SQUAWKABILLY, Type.NORMAL, Type.FLYING, [ @@ -6539,30 +6539,30 @@ export function initBiomes() { ] ], [ Species.CAPSAKID, Type.GRASS, -1, [ - [ Biome.BADLANDS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.BADLANDS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.SCOVILLAIN, Type.GRASS, Type.FIRE, [ - [ Biome.BADLANDS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.BADLANDS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.BADLANDS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.BADLANDS, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.RELLOR, Type.BUG, -1, [ - [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.RABSCA, Type.BUG, Type.PSYCHIC, [ - [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.DESERT, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.DESERT, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.DESERT, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.FLITTLE, Type.PSYCHIC, -1, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.ESPATHRA, Type.PSYCHIC, -1, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.MOUNTAIN, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.TINKATINK, Type.FAIRY, Type.STEEL, [ @@ -6587,16 +6587,16 @@ export function initBiomes() { ] ], [ Species.BOMBIRDIER, Type.FLYING, Type.DARK, [ - [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.FINIZEN, Type.WATER, -1, [ - [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.PALAFIN, Type.WATER, -1, [ - [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SEA, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SEA, BiomePoolTier.COMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SEA, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.VAROOM, Type.STEEL, Type.POISON, [ @@ -6664,14 +6664,14 @@ export function initBiomes() { ] ], [ Species.ANNIHILAPE, Type.FIGHTING, Type.GHOST, [ - [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], + [ Biome.PLAINS, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], [ Biome.DOJO, BiomePoolTier.COMMON ], [ Biome.DOJO, BiomePoolTier.BOSS ] ] ], [ Species.CLODSIRE, Type.POISON, Type.GROUND, [ - [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SWAMP, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SWAMP, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.FARIGIRAF, Type.NORMAL, Type.PSYCHIC, [ @@ -6867,17 +6867,17 @@ export function initBiomes() { [ Species.PECHARUNT, Type.POISON, Type.GHOST, [ ] ], [ Species.ALOLA_RATTATA, Type.DARK, Type.NORMAL, [ - [ Biome.ISLAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.ISLAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.ALOLA_RATICATE, Type.DARK, Type.NORMAL, [ - [ Biome.ISLAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.ISLAND, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.ISLAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.ISLAND, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.ALOLA_RAICHU, Type.ELECTRIC, Type.PSYCHIC, [ - [ Biome.ISLAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.ISLAND, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.ISLAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.ISLAND, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.ALOLA_SANDSHREW, Type.ICE, Type.STEEL, [ @@ -6914,12 +6914,12 @@ export function initBiomes() { ] ], [ Species.ALOLA_MEOWTH, Type.DARK, -1, [ - [ Biome.ISLAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.ISLAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.ALOLA_PERSIAN, Type.DARK, -1, [ - [ Biome.ISLAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.ISLAND, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.ISLAND, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.ISLAND, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.ALOLA_GEODUDE, Type.ROCK, Type.ELECTRIC, [ @@ -6945,13 +6945,13 @@ export function initBiomes() { ] ], [ Species.ALOLA_EXEGGUTOR, Type.GRASS, Type.DRAGON, [ - [ Biome.ISLAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.ISLAND, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.ISLAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.ISLAND, BiomePoolTier.BOSS, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.ALOLA_MAROWAK, Type.FIRE, Type.GHOST, [ - [ Biome.ISLAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.ISLAND, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.ISLAND, BiomePoolTier.UNCOMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.ISLAND, BiomePoolTier.BOSS, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.ETERNAL_FLOETTE, Type.FAIRY, -1, [ @@ -6973,12 +6973,12 @@ export function initBiomes() { ] ], [ Species.GALAR_SLOWPOKE, Type.PSYCHIC, -1, [ - [ Biome.SWAMP, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SWAMP, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GALAR_SLOWBRO, Type.POISON, Type.PSYCHIC, [ - [ Biome.SWAMP, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SWAMP, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SWAMP, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SWAMP, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GALAR_FARFETCHD, Type.FIGHTING, -1, [ @@ -7009,7 +7009,7 @@ export function initBiomes() { ] ], [ Species.GALAR_SLOWKING, Type.POISON, Type.PSYCHIC, [ - [ Biome.SWAMP, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SWAMP, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GALAR_CORSOLA, Type.GHOST, -1, [ @@ -7017,24 +7017,24 @@ export function initBiomes() { ] ], [ Species.GALAR_ZIGZAGOON, Type.DARK, Type.NORMAL, [ - [ Biome.SLUM, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SLUM, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.GALAR_LINOONE, Type.DARK, Type.NORMAL, [ - [ Biome.SLUM, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SLUM, BiomePoolTier.RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.GALAR_DARUMAKA, Type.ICE, -1, [ - [ Biome.SNOWY_FOREST, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GALAR_DARMANITAN, Type.ICE, -1, [ - [ Biome.SNOWY_FOREST, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SNOWY_FOREST, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SNOWY_FOREST, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.GALAR_YAMASK, Type.GROUND, Type.GHOST, [ - [ Biome.RUINS, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.RUINS, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.GALAR_STUNFISK, Type.GROUND, Type.STEEL, [ @@ -7067,7 +7067,7 @@ export function initBiomes() { ] ], [ Species.HISUI_SNEASEL, Type.FIGHTING, Type.POISON, [ - [ Biome.SNOWY_FOREST, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.HISUI_SAMUROTT, Type.WATER, Type.DARK, [ @@ -7075,29 +7075,29 @@ export function initBiomes() { ] ], [ Species.HISUI_LILLIGANT, Type.GRASS, Type.FIGHTING, [ - [ Biome.MEADOW, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MEADOW, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.HISUI_ZORUA, Type.NORMAL, Type.GHOST, [ - [ Biome.SNOWY_FOREST, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.HISUI_ZOROARK, Type.NORMAL, Type.GHOST, [ - [ Biome.SNOWY_FOREST, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ], - [ Biome.SNOWY_FOREST, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SNOWY_FOREST, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]], + [ Biome.SNOWY_FOREST, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.HISUI_BRAVIARY, Type.PSYCHIC, Type.FLYING, [ - [ Biome.MOUNTAIN, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.MOUNTAIN, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.HISUI_SLIGGOO, Type.STEEL, Type.DRAGON, [ - [ Biome.SWAMP, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SWAMP, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.HISUI_GOODRA, Type.STEEL, Type.DRAGON, [ - [ Biome.SWAMP, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.SWAMP, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.SWAMP, BiomePoolTier.SUPER_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.SWAMP, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.HISUI_AVALUGG, Type.ICE, Type.ROCK, [ @@ -7109,12 +7109,12 @@ export function initBiomes() { ] ], [ Species.PALDEA_TAUROS, Type.FIGHTING, -1, [ - [ Biome.PLAINS, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ], - [ Biome.PLAINS, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ] ] + [ Biome.PLAINS, BiomePoolTier.RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]], + [ Biome.PLAINS, BiomePoolTier.BOSS_RARE, [ TimeOfDay.DAWN, TimeOfDay.DAY ]] ] ], [ Species.PALDEA_WOOPER, Type.POISON, Type.GROUND, [ - [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ] ] + [ Biome.SWAMP, BiomePoolTier.COMMON, [ TimeOfDay.DUSK, TimeOfDay.NIGHT ]] ] ], [ Species.BLOODMOON_URSALUNA, Type.GROUND, Type.NORMAL, [ @@ -7146,7 +7146,7 @@ export function initBiomes() { [ Biome.METROPOLIS, BiomePoolTier.RARE ] ] ], - [ TrainerType.BACKERS, [] ], + [ TrainerType.BACKERS, []], [ TrainerType.BACKPACKER, [ [ Biome.MOUNTAIN, BiomePoolTier.COMMON ], [ Biome.CAVE, BiomePoolTier.COMMON ], @@ -7160,7 +7160,7 @@ export function initBiomes() { ], [ TrainerType.BEAUTY, [ [ Biome.FAIRY_CAVE, BiomePoolTier.COMMON ] - ] ], + ]], [ TrainerType.BIKER, [ [ Biome.SLUM, BiomePoolTier.COMMON ] ] @@ -7190,42 +7190,42 @@ export function initBiomes() { ], [ TrainerType.CLERK, [ [ Biome.METROPOLIS, BiomePoolTier.COMMON ] - ] ], + ]], [ TrainerType.CYCLIST, [ [ Biome.PLAINS, BiomePoolTier.UNCOMMON ], [ Biome.METROPOLIS, BiomePoolTier.COMMON ] ] ], - [ TrainerType.DANCER, [] ], + [ TrainerType.DANCER, []], [ TrainerType.DEPOT_AGENT, [ [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON ] - ] ], - [ TrainerType.DOCTOR, [] ], + ]], + [ TrainerType.DOCTOR, []], [ TrainerType.FISHERMAN, [ [ Biome.LAKE, BiomePoolTier.COMMON ], [ Biome.BEACH, BiomePoolTier.COMMON ] ] ], - [ TrainerType.RICH, [] ], + [ TrainerType.RICH, []], [ TrainerType.GUITARIST, [ [ Biome.METROPOLIS, BiomePoolTier.UNCOMMON ], [ Biome.POWER_PLANT, BiomePoolTier.COMMON ] - ] ], - [ TrainerType.HARLEQUIN, [] ], + ]], + [ TrainerType.HARLEQUIN, []], [ TrainerType.HIKER, [ [ Biome.MOUNTAIN, BiomePoolTier.COMMON ], [ Biome.CAVE, BiomePoolTier.COMMON ], [ Biome.BADLANDS, BiomePoolTier.COMMON ] ] ], - [ TrainerType.HOOLIGANS, [] ], - [ TrainerType.HOOPSTER, [] ], - [ TrainerType.INFIELDER, [] ], - [ TrainerType.JANITOR, [] ], - [ TrainerType.LINEBACKER, [] ], - [ TrainerType.MAID, [] ], - [ TrainerType.MUSICIAN, [] ], - [ TrainerType.NURSERY_AIDE, [] ], + [ TrainerType.HOOLIGANS, []], + [ TrainerType.HOOPSTER, []], + [ TrainerType.INFIELDER, []], + [ TrainerType.JANITOR, []], + [ TrainerType.LINEBACKER, []], + [ TrainerType.MAID, []], + [ TrainerType.MUSICIAN, []], + [ TrainerType.NURSERY_AIDE, []], [ TrainerType.OFFICER, [ [ Biome.METROPOLIS, BiomePoolTier.COMMON ], [ Biome.CONSTRUCTION_SITE, BiomePoolTier.COMMON ], @@ -7237,9 +7237,9 @@ export function initBiomes() { [ Biome.MEADOW, BiomePoolTier.COMMON ] ] ], - [ TrainerType.PILOT, [] ], - [ TrainerType.POKEFAN, [] ], - [ TrainerType.PRESCHOOLER, [] ], + [ TrainerType.PILOT, []], + [ TrainerType.POKEFAN, []], + [ TrainerType.PRESCHOOLER, []], [ TrainerType.PSYCHIC, [ [ Biome.GRAVEYARD, BiomePoolTier.COMMON ], [ Biome.RUINS, BiomePoolTier.COMMON ] @@ -7251,7 +7251,7 @@ export function initBiomes() { [ Biome.JUNGLE, BiomePoolTier.COMMON ] ] ], - [ TrainerType.RICH_KID, [] ], + [ TrainerType.RICH_KID, []], [ TrainerType.ROUGHNECK, [ [ Biome.SLUM, BiomePoolTier.COMMON ] ] @@ -7261,13 +7261,13 @@ export function initBiomes() { [ Biome.RUINS, BiomePoolTier.COMMON ] ] ], - [ TrainerType.SMASHER, [] ], + [ TrainerType.SMASHER, []], [ TrainerType.SNOW_WORKER, [ [ Biome.ICE_CAVE, BiomePoolTier.COMMON ], [ Biome.SNOWY_FOREST, BiomePoolTier.COMMON ] ] ], - [ TrainerType.STRIKER, [] ], + [ TrainerType.STRIKER, []], [ TrainerType.SCHOOL_KID, [ [ Biome.GRASS, BiomePoolTier.COMMON ] ] @@ -7607,57 +7607,57 @@ export function initBiomes() { [ Biome.ICE_CAVE, BiomePoolTier.BOSS ] ] ], - [ TrainerType.LORELEI, [] ], - [ TrainerType.BRUNO, [] ], - [ TrainerType.AGATHA, [] ], - [ TrainerType.LANCE, [] ], - [ TrainerType.WILL, [] ], - [ TrainerType.KOGA, [] ], - [ TrainerType.KAREN, [] ], - [ TrainerType.SIDNEY, [] ], - [ TrainerType.PHOEBE, [] ], - [ TrainerType.GLACIA, [] ], - [ TrainerType.DRAKE, [] ], - [ TrainerType.AARON, [] ], - [ TrainerType.BERTHA, [] ], - [ TrainerType.FLINT, [] ], - [ TrainerType.LUCIAN, [] ], - [ TrainerType.SHAUNTAL, [] ], - [ TrainerType.MARSHAL, [] ], - [ TrainerType.GRIMSLEY, [] ], - [ TrainerType.CAITLIN, [] ], - [ TrainerType.MALVA, [] ], - [ TrainerType.SIEBOLD, [] ], - [ TrainerType.WIKSTROM, [] ], - [ TrainerType.DRASNA, [] ], - [ TrainerType.HALA, [] ], - [ TrainerType.MOLAYNE, [] ], - [ TrainerType.OLIVIA, [] ], - [ TrainerType.ACEROLA, [] ], - [ TrainerType.KAHILI, [] ], - [ TrainerType.RIKA, [] ], - [ TrainerType.POPPY, [] ], - [ TrainerType.LARRY_ELITE, [] ], - [ TrainerType.HASSEL, [] ], - [ TrainerType.CRISPIN, [] ], - [ TrainerType.AMARYS, [] ], - [ TrainerType.LACEY, [] ], - [ TrainerType.DRAYTON, [] ], - [ TrainerType.BLUE, [] ], - [ TrainerType.RED, [] ], - [ TrainerType.LANCE_CHAMPION, [] ], - [ TrainerType.STEVEN, [] ], - [ TrainerType.WALLACE, [] ], - [ TrainerType.CYNTHIA, [] ], - [ TrainerType.ALDER, [] ], - [ TrainerType.IRIS, [] ], - [ TrainerType.DIANTHA, [] ], - [ TrainerType.HAU, [] ], - [ TrainerType.GEETA, [] ], - [ TrainerType.NEMONA, [] ], - [ TrainerType.KIERAN, [] ], - [ TrainerType.LEON, [] ], - [ TrainerType.RIVAL, [] ] + [ TrainerType.LORELEI, []], + [ TrainerType.BRUNO, []], + [ TrainerType.AGATHA, []], + [ TrainerType.LANCE, []], + [ TrainerType.WILL, []], + [ TrainerType.KOGA, []], + [ TrainerType.KAREN, []], + [ TrainerType.SIDNEY, []], + [ TrainerType.PHOEBE, []], + [ TrainerType.GLACIA, []], + [ TrainerType.DRAKE, []], + [ TrainerType.AARON, []], + [ TrainerType.BERTHA, []], + [ TrainerType.FLINT, []], + [ TrainerType.LUCIAN, []], + [ TrainerType.SHAUNTAL, []], + [ TrainerType.MARSHAL, []], + [ TrainerType.GRIMSLEY, []], + [ TrainerType.CAITLIN, []], + [ TrainerType.MALVA, []], + [ TrainerType.SIEBOLD, []], + [ TrainerType.WIKSTROM, []], + [ TrainerType.DRASNA, []], + [ TrainerType.HALA, []], + [ TrainerType.MOLAYNE, []], + [ TrainerType.OLIVIA, []], + [ TrainerType.ACEROLA, []], + [ TrainerType.KAHILI, []], + [ TrainerType.RIKA, []], + [ TrainerType.POPPY, []], + [ TrainerType.LARRY_ELITE, []], + [ TrainerType.HASSEL, []], + [ TrainerType.CRISPIN, []], + [ TrainerType.AMARYS, []], + [ TrainerType.LACEY, []], + [ TrainerType.DRAYTON, []], + [ TrainerType.BLUE, []], + [ TrainerType.RED, []], + [ TrainerType.LANCE_CHAMPION, []], + [ TrainerType.STEVEN, []], + [ TrainerType.WALLACE, []], + [ TrainerType.CYNTHIA, []], + [ TrainerType.ALDER, []], + [ TrainerType.IRIS, []], + [ TrainerType.DIANTHA, []], + [ TrainerType.HAU, []], + [ TrainerType.GEETA, []], + [ TrainerType.NEMONA, []], + [ TrainerType.KIERAN, []], + [ TrainerType.LEON, []], + [ TrainerType.RIVAL, []] ]; biomeDepths[Biome.TOWN] = [ 0, 1 ]; diff --git a/src/data/balance/species-egg-tiers.ts b/src/data/balance/species-egg-tiers.ts new file mode 100644 index 00000000000..cd266dfcf54 --- /dev/null +++ b/src/data/balance/species-egg-tiers.ts @@ -0,0 +1,603 @@ +import { Species } from "#enums/species"; +import { EggTier } from "#enums/egg-type"; + +/** + * Map of all starters and their respective {@linkcode EggTier}, which determines the type of egg the starter hatches from. + */ +export const speciesEggTiers = { + [Species.BULBASAUR]: EggTier.COMMON, + [Species.CHARMANDER]: EggTier.COMMON, + [Species.SQUIRTLE]: EggTier.COMMON, + [Species.CATERPIE]: EggTier.COMMON, + [Species.WEEDLE]: EggTier.COMMON, + [Species.PIDGEY]: EggTier.COMMON, + [Species.RATTATA]: EggTier.COMMON, + [Species.SPEAROW]: EggTier.COMMON, + [Species.EKANS]: EggTier.COMMON, + [Species.PIKACHU]: EggTier.COMMON, + [Species.SANDSHREW]: EggTier.COMMON, + [Species.NIDORAN_F]: EggTier.COMMON, + [Species.NIDORAN_M]: EggTier.COMMON, + [Species.CLEFAIRY]: EggTier.COMMON, + [Species.VULPIX]: EggTier.COMMON, + [Species.JIGGLYPUFF]: EggTier.COMMON, + [Species.ZUBAT]: EggTier.COMMON, + [Species.ODDISH]: EggTier.COMMON, + [Species.PARAS]: EggTier.COMMON, + [Species.VENONAT]: EggTier.COMMON, + [Species.DIGLETT]: EggTier.COMMON, + [Species.MEOWTH]: EggTier.COMMON, + [Species.PSYDUCK]: EggTier.COMMON, + [Species.MANKEY]: EggTier.RARE, + [Species.GROWLITHE]: EggTier.RARE, + [Species.POLIWAG]: EggTier.COMMON, + [Species.ABRA]: EggTier.RARE, + [Species.MACHOP]: EggTier.COMMON, + [Species.BELLSPROUT]: EggTier.COMMON, + [Species.TENTACOOL]: EggTier.COMMON, + [Species.GEODUDE]: EggTier.COMMON, + [Species.PONYTA]: EggTier.COMMON, + [Species.SLOWPOKE]: EggTier.COMMON, + [Species.MAGNEMITE]: EggTier.RARE, + [Species.FARFETCHD]: EggTier.COMMON, + [Species.DODUO]: EggTier.COMMON, + [Species.SEEL]: EggTier.COMMON, + [Species.GRIMER]: EggTier.COMMON, + [Species.SHELLDER]: EggTier.RARE, + [Species.GASTLY]: EggTier.RARE, + [Species.ONIX]: EggTier.COMMON, + [Species.DROWZEE]: EggTier.COMMON, + [Species.KRABBY]: EggTier.COMMON, + [Species.VOLTORB]: EggTier.COMMON, + [Species.EXEGGCUTE]: EggTier.COMMON, + [Species.CUBONE]: EggTier.COMMON, + [Species.HITMONLEE]: EggTier.RARE, + [Species.HITMONCHAN]: EggTier.RARE, + [Species.LICKITUNG]: EggTier.COMMON, + [Species.KOFFING]: EggTier.COMMON, + [Species.RHYHORN]: EggTier.COMMON, + [Species.CHANSEY]: EggTier.COMMON, + [Species.TANGELA]: EggTier.COMMON, + [Species.KANGASKHAN]: EggTier.RARE, + [Species.HORSEA]: EggTier.COMMON, + [Species.GOLDEEN]: EggTier.COMMON, + [Species.STARYU]: EggTier.COMMON, + [Species.MR_MIME]: EggTier.COMMON, + [Species.SCYTHER]: EggTier.RARE, + [Species.JYNX]: EggTier.RARE, + [Species.ELECTABUZZ]: EggTier.RARE, + [Species.MAGMAR]: EggTier.RARE, + [Species.PINSIR]: EggTier.RARE, + [Species.TAUROS]: EggTier.RARE, + [Species.MAGIKARP]: EggTier.RARE, + [Species.LAPRAS]: EggTier.RARE, + [Species.DITTO]: EggTier.COMMON, + [Species.EEVEE]: EggTier.COMMON, + [Species.PORYGON]: EggTier.RARE, + [Species.OMANYTE]: EggTier.COMMON, + [Species.KABUTO]: EggTier.COMMON, + [Species.AERODACTYL]: EggTier.RARE, + [Species.SNORLAX]: EggTier.RARE, + [Species.ARTICUNO]: EggTier.EPIC, + [Species.ZAPDOS]: EggTier.EPIC, + [Species.MOLTRES]: EggTier.EPIC, + [Species.DRATINI]: EggTier.RARE, + [Species.MEWTWO]: EggTier.LEGENDARY, + [Species.MEW]: EggTier.EPIC, + + [Species.CHIKORITA]: EggTier.COMMON, + [Species.CYNDAQUIL]: EggTier.COMMON, + [Species.TOTODILE]: EggTier.COMMON, + [Species.SENTRET]: EggTier.COMMON, + [Species.HOOTHOOT]: EggTier.COMMON, + [Species.LEDYBA]: EggTier.COMMON, + [Species.SPINARAK]: EggTier.COMMON, + [Species.CHINCHOU]: EggTier.COMMON, + [Species.PICHU]: EggTier.COMMON, + [Species.CLEFFA]: EggTier.COMMON, + [Species.IGGLYBUFF]: EggTier.COMMON, + [Species.TOGEPI]: EggTier.COMMON, + [Species.NATU]: EggTier.COMMON, + [Species.MAREEP]: EggTier.COMMON, + [Species.MARILL]: EggTier.RARE, + [Species.SUDOWOODO]: EggTier.COMMON, + [Species.HOPPIP]: EggTier.COMMON, + [Species.AIPOM]: EggTier.COMMON, + [Species.SUNKERN]: EggTier.COMMON, + [Species.YANMA]: EggTier.COMMON, + [Species.WOOPER]: EggTier.COMMON, + [Species.MURKROW]: EggTier.COMMON, + [Species.MISDREAVUS]: EggTier.COMMON, + [Species.UNOWN]: EggTier.COMMON, + [Species.WOBBUFFET]: EggTier.COMMON, + [Species.GIRAFARIG]: EggTier.COMMON, + [Species.PINECO]: EggTier.COMMON, + [Species.DUNSPARCE]: EggTier.COMMON, + [Species.GLIGAR]: EggTier.COMMON, + [Species.SNUBBULL]: EggTier.COMMON, + [Species.QWILFISH]: EggTier.COMMON, + [Species.SHUCKLE]: EggTier.COMMON, + [Species.HERACROSS]: EggTier.RARE, + [Species.SNEASEL]: EggTier.RARE, + [Species.TEDDIURSA]: EggTier.RARE, + [Species.SLUGMA]: EggTier.COMMON, + [Species.SWINUB]: EggTier.COMMON, + [Species.CORSOLA]: EggTier.COMMON, + [Species.REMORAID]: EggTier.COMMON, + [Species.DELIBIRD]: EggTier.COMMON, + [Species.MANTINE]: EggTier.COMMON, + [Species.SKARMORY]: EggTier.RARE, + [Species.HOUNDOUR]: EggTier.COMMON, + [Species.PHANPY]: EggTier.COMMON, + [Species.STANTLER]: EggTier.COMMON, + [Species.SMEARGLE]: EggTier.COMMON, + [Species.TYROGUE]: EggTier.COMMON, + [Species.SMOOCHUM]: EggTier.COMMON, + [Species.ELEKID]: EggTier.COMMON, + [Species.MAGBY]: EggTier.COMMON, + [Species.MILTANK]: EggTier.RARE, + [Species.RAIKOU]: EggTier.EPIC, + [Species.ENTEI]: EggTier.EPIC, + [Species.SUICUNE]: EggTier.EPIC, + [Species.LARVITAR]: EggTier.RARE, + [Species.LUGIA]: EggTier.LEGENDARY, + [Species.HO_OH]: EggTier.LEGENDARY, + [Species.CELEBI]: EggTier.EPIC, + + [Species.TREECKO]: EggTier.COMMON, + [Species.TORCHIC]: EggTier.RARE, + [Species.MUDKIP]: EggTier.COMMON, + [Species.POOCHYENA]: EggTier.COMMON, + [Species.ZIGZAGOON]: EggTier.COMMON, + [Species.WURMPLE]: EggTier.COMMON, + [Species.LOTAD]: EggTier.COMMON, + [Species.SEEDOT]: EggTier.COMMON, + [Species.TAILLOW]: EggTier.COMMON, + [Species.WINGULL]: EggTier.COMMON, + [Species.RALTS]: EggTier.COMMON, + [Species.SURSKIT]: EggTier.COMMON, + [Species.SHROOMISH]: EggTier.COMMON, + [Species.SLAKOTH]: EggTier.RARE, + [Species.NINCADA]: EggTier.RARE, + [Species.WHISMUR]: EggTier.COMMON, + [Species.MAKUHITA]: EggTier.COMMON, + [Species.AZURILL]: EggTier.RARE, + [Species.NOSEPASS]: EggTier.COMMON, + [Species.SKITTY]: EggTier.COMMON, + [Species.SABLEYE]: EggTier.COMMON, + [Species.MAWILE]: EggTier.COMMON, + [Species.ARON]: EggTier.COMMON, + [Species.MEDITITE]: EggTier.COMMON, + [Species.ELECTRIKE]: EggTier.COMMON, + [Species.PLUSLE]: EggTier.COMMON, + [Species.MINUN]: EggTier.COMMON, + [Species.VOLBEAT]: EggTier.COMMON, + [Species.ILLUMISE]: EggTier.COMMON, + [Species.ROSELIA]: EggTier.COMMON, + [Species.GULPIN]: EggTier.COMMON, + [Species.CARVANHA]: EggTier.COMMON, + [Species.WAILMER]: EggTier.COMMON, + [Species.NUMEL]: EggTier.COMMON, + [Species.TORKOAL]: EggTier.COMMON, + [Species.SPOINK]: EggTier.COMMON, + [Species.SPINDA]: EggTier.COMMON, + [Species.TRAPINCH]: EggTier.COMMON, + [Species.CACNEA]: EggTier.COMMON, + [Species.SWABLU]: EggTier.COMMON, + [Species.ZANGOOSE]: EggTier.RARE, + [Species.SEVIPER]: EggTier.COMMON, + [Species.LUNATONE]: EggTier.COMMON, + [Species.SOLROCK]: EggTier.COMMON, + [Species.BARBOACH]: EggTier.COMMON, + [Species.CORPHISH]: EggTier.COMMON, + [Species.BALTOY]: EggTier.COMMON, + [Species.LILEEP]: EggTier.COMMON, + [Species.ANORITH]: EggTier.COMMON, + [Species.FEEBAS]: EggTier.RARE, + [Species.CASTFORM]: EggTier.COMMON, + [Species.KECLEON]: EggTier.COMMON, + [Species.SHUPPET]: EggTier.COMMON, + [Species.DUSKULL]: EggTier.COMMON, + [Species.TROPIUS]: EggTier.COMMON, + [Species.CHIMECHO]: EggTier.COMMON, + [Species.ABSOL]: EggTier.RARE, + [Species.WYNAUT]: EggTier.COMMON, + [Species.SNORUNT]: EggTier.COMMON, + [Species.SPHEAL]: EggTier.COMMON, + [Species.CLAMPERL]: EggTier.COMMON, + [Species.RELICANTH]: EggTier.COMMON, + [Species.LUVDISC]: EggTier.COMMON, + [Species.BAGON]: EggTier.RARE, + [Species.BELDUM]: EggTier.RARE, + [Species.REGIROCK]: EggTier.EPIC, + [Species.REGICE]: EggTier.EPIC, + [Species.REGISTEEL]: EggTier.EPIC, + [Species.LATIAS]: EggTier.EPIC, + [Species.LATIOS]: EggTier.EPIC, + [Species.KYOGRE]: EggTier.LEGENDARY, + [Species.GROUDON]: EggTier.LEGENDARY, + [Species.RAYQUAZA]: EggTier.LEGENDARY, + [Species.JIRACHI]: EggTier.EPIC, + [Species.DEOXYS]: EggTier.EPIC, + + [Species.TURTWIG]: EggTier.COMMON, + [Species.CHIMCHAR]: EggTier.COMMON, + [Species.PIPLUP]: EggTier.COMMON, + [Species.STARLY]: EggTier.COMMON, + [Species.BIDOOF]: EggTier.COMMON, + [Species.KRICKETOT]: EggTier.COMMON, + [Species.SHINX]: EggTier.COMMON, + [Species.BUDEW]: EggTier.COMMON, + [Species.CRANIDOS]: EggTier.COMMON, + [Species.SHIELDON]: EggTier.COMMON, + [Species.BURMY]: EggTier.COMMON, + [Species.COMBEE]: EggTier.COMMON, + [Species.PACHIRISU]: EggTier.COMMON, + [Species.BUIZEL]: EggTier.COMMON, + [Species.CHERUBI]: EggTier.COMMON, + [Species.SHELLOS]: EggTier.COMMON, + [Species.DRIFLOON]: EggTier.COMMON, + [Species.BUNEARY]: EggTier.COMMON, + [Species.GLAMEOW]: EggTier.COMMON, + [Species.CHINGLING]: EggTier.COMMON, + [Species.STUNKY]: EggTier.COMMON, + [Species.BRONZOR]: EggTier.COMMON, + [Species.BONSLY]: EggTier.COMMON, + [Species.MIME_JR]: EggTier.COMMON, + [Species.HAPPINY]: EggTier.COMMON, + [Species.CHATOT]: EggTier.COMMON, + [Species.SPIRITOMB]: EggTier.RARE, + [Species.GIBLE]: EggTier.RARE, + [Species.MUNCHLAX]: EggTier.RARE, + [Species.RIOLU]: EggTier.COMMON, + [Species.HIPPOPOTAS]: EggTier.COMMON, + [Species.SKORUPI]: EggTier.COMMON, + [Species.CROAGUNK]: EggTier.COMMON, + [Species.CARNIVINE]: EggTier.COMMON, + [Species.FINNEON]: EggTier.COMMON, + [Species.MANTYKE]: EggTier.COMMON, + [Species.SNOVER]: EggTier.COMMON, + [Species.ROTOM]: EggTier.RARE, + [Species.UXIE]: EggTier.EPIC, + [Species.MESPRIT]: EggTier.EPIC, + [Species.AZELF]: EggTier.EPIC, + [Species.DIALGA]: EggTier.LEGENDARY, + [Species.PALKIA]: EggTier.LEGENDARY, + [Species.HEATRAN]: EggTier.EPIC, + [Species.REGIGIGAS]: EggTier.EPIC, + [Species.GIRATINA]: EggTier.LEGENDARY, + [Species.CRESSELIA]: EggTier.EPIC, + [Species.PHIONE]: EggTier.RARE, + [Species.MANAPHY]: EggTier.EPIC, + [Species.DARKRAI]: EggTier.EPIC, + [Species.SHAYMIN]: EggTier.EPIC, + [Species.ARCEUS]: EggTier.LEGENDARY, + + [Species.VICTINI]: EggTier.EPIC, + [Species.SNIVY]: EggTier.COMMON, + [Species.TEPIG]: EggTier.COMMON, + [Species.OSHAWOTT]: EggTier.COMMON, + [Species.PATRAT]: EggTier.COMMON, + [Species.LILLIPUP]: EggTier.COMMON, + [Species.PURRLOIN]: EggTier.COMMON, + [Species.PANSAGE]: EggTier.COMMON, + [Species.PANSEAR]: EggTier.COMMON, + [Species.PANPOUR]: EggTier.COMMON, + [Species.MUNNA]: EggTier.COMMON, + [Species.PIDOVE]: EggTier.COMMON, + [Species.BLITZLE]: EggTier.COMMON, + [Species.ROGGENROLA]: EggTier.COMMON, + [Species.WOOBAT]: EggTier.COMMON, + [Species.DRILBUR]: EggTier.RARE, + [Species.AUDINO]: EggTier.COMMON, + [Species.TIMBURR]: EggTier.RARE, + [Species.TYMPOLE]: EggTier.COMMON, + [Species.THROH]: EggTier.RARE, + [Species.SAWK]: EggTier.RARE, + [Species.SEWADDLE]: EggTier.COMMON, + [Species.VENIPEDE]: EggTier.COMMON, + [Species.COTTONEE]: EggTier.COMMON, + [Species.PETILIL]: EggTier.COMMON, + [Species.BASCULIN]: EggTier.RARE, + [Species.SANDILE]: EggTier.RARE, + [Species.DARUMAKA]: EggTier.RARE, + [Species.MARACTUS]: EggTier.COMMON, + [Species.DWEBBLE]: EggTier.COMMON, + [Species.SCRAGGY]: EggTier.COMMON, + [Species.SIGILYPH]: EggTier.RARE, + [Species.YAMASK]: EggTier.COMMON, + [Species.TIRTOUGA]: EggTier.COMMON, + [Species.ARCHEN]: EggTier.COMMON, + [Species.TRUBBISH]: EggTier.COMMON, + [Species.ZORUA]: EggTier.COMMON, + [Species.MINCCINO]: EggTier.COMMON, + [Species.GOTHITA]: EggTier.COMMON, + [Species.SOLOSIS]: EggTier.COMMON, + [Species.DUCKLETT]: EggTier.COMMON, + [Species.VANILLITE]: EggTier.COMMON, + [Species.DEERLING]: EggTier.COMMON, + [Species.EMOLGA]: EggTier.COMMON, + [Species.KARRABLAST]: EggTier.COMMON, + [Species.FOONGUS]: EggTier.COMMON, + [Species.FRILLISH]: EggTier.COMMON, + [Species.ALOMOMOLA]: EggTier.RARE, + [Species.JOLTIK]: EggTier.COMMON, + [Species.FERROSEED]: EggTier.COMMON, + [Species.KLINK]: EggTier.COMMON, + [Species.TYNAMO]: EggTier.COMMON, + [Species.ELGYEM]: EggTier.COMMON, + [Species.LITWICK]: EggTier.COMMON, + [Species.AXEW]: EggTier.RARE, + [Species.CUBCHOO]: EggTier.COMMON, + [Species.CRYOGONAL]: EggTier.RARE, + [Species.SHELMET]: EggTier.COMMON, + [Species.STUNFISK]: EggTier.COMMON, + [Species.MIENFOO]: EggTier.COMMON, + [Species.DRUDDIGON]: EggTier.RARE, + [Species.GOLETT]: EggTier.COMMON, + [Species.PAWNIARD]: EggTier.RARE, + [Species.BOUFFALANT]: EggTier.RARE, + [Species.RUFFLET]: EggTier.COMMON, + [Species.VULLABY]: EggTier.COMMON, + [Species.HEATMOR]: EggTier.COMMON, + [Species.DURANT]: EggTier.RARE, + [Species.DEINO]: EggTier.RARE, + [Species.LARVESTA]: EggTier.RARE, + [Species.COBALION]: EggTier.EPIC, + [Species.TERRAKION]: EggTier.EPIC, + [Species.VIRIZION]: EggTier.EPIC, + [Species.TORNADUS]: EggTier.EPIC, + [Species.THUNDURUS]: EggTier.EPIC, + [Species.RESHIRAM]: EggTier.LEGENDARY, + [Species.ZEKROM]: EggTier.LEGENDARY, + [Species.LANDORUS]: EggTier.EPIC, + [Species.KYUREM]: EggTier.LEGENDARY, + [Species.KELDEO]: EggTier.EPIC, + [Species.MELOETTA]: EggTier.EPIC, + [Species.GENESECT]: EggTier.EPIC, + + [Species.CHESPIN]: EggTier.COMMON, + [Species.FENNEKIN]: EggTier.COMMON, + [Species.FROAKIE]: EggTier.RARE, + [Species.BUNNELBY]: EggTier.COMMON, + [Species.FLETCHLING]: EggTier.COMMON, + [Species.SCATTERBUG]: EggTier.COMMON, + [Species.LITLEO]: EggTier.COMMON, + [Species.FLABEBE]: EggTier.COMMON, + [Species.SKIDDO]: EggTier.COMMON, + [Species.PANCHAM]: EggTier.COMMON, + [Species.FURFROU]: EggTier.COMMON, + [Species.ESPURR]: EggTier.COMMON, + [Species.HONEDGE]: EggTier.RARE, + [Species.SPRITZEE]: EggTier.COMMON, + [Species.SWIRLIX]: EggTier.COMMON, + [Species.INKAY]: EggTier.COMMON, + [Species.BINACLE]: EggTier.COMMON, + [Species.SKRELP]: EggTier.COMMON, + [Species.CLAUNCHER]: EggTier.COMMON, + [Species.HELIOPTILE]: EggTier.COMMON, + [Species.TYRUNT]: EggTier.COMMON, + [Species.AMAURA]: EggTier.COMMON, + [Species.HAWLUCHA]: EggTier.RARE, + [Species.DEDENNE]: EggTier.COMMON, + [Species.CARBINK]: EggTier.COMMON, + [Species.GOOMY]: EggTier.RARE, + [Species.KLEFKI]: EggTier.COMMON, + [Species.PHANTUMP]: EggTier.COMMON, + [Species.PUMPKABOO]: EggTier.COMMON, + [Species.BERGMITE]: EggTier.COMMON, + [Species.NOIBAT]: EggTier.COMMON, + [Species.XERNEAS]: EggTier.LEGENDARY, + [Species.YVELTAL]: EggTier.LEGENDARY, + [Species.ZYGARDE]: EggTier.LEGENDARY, + [Species.DIANCIE]: EggTier.EPIC, + [Species.HOOPA]: EggTier.EPIC, + [Species.VOLCANION]: EggTier.EPIC, + [Species.ETERNAL_FLOETTE]: EggTier.RARE, + + [Species.ROWLET]: EggTier.COMMON, + [Species.LITTEN]: EggTier.COMMON, + [Species.POPPLIO]: EggTier.RARE, + [Species.PIKIPEK]: EggTier.COMMON, + [Species.YUNGOOS]: EggTier.COMMON, + [Species.GRUBBIN]: EggTier.COMMON, + [Species.CRABRAWLER]: EggTier.COMMON, + [Species.ORICORIO]: EggTier.COMMON, + [Species.CUTIEFLY]: EggTier.COMMON, + [Species.ROCKRUFF]: EggTier.COMMON, + [Species.WISHIWASHI]: EggTier.COMMON, + [Species.MAREANIE]: EggTier.COMMON, + [Species.MUDBRAY]: EggTier.COMMON, + [Species.DEWPIDER]: EggTier.COMMON, + [Species.FOMANTIS]: EggTier.COMMON, + [Species.MORELULL]: EggTier.COMMON, + [Species.SALANDIT]: EggTier.COMMON, + [Species.STUFFUL]: EggTier.COMMON, + [Species.BOUNSWEET]: EggTier.COMMON, + [Species.COMFEY]: EggTier.RARE, + [Species.ORANGURU]: EggTier.RARE, + [Species.PASSIMIAN]: EggTier.RARE, + [Species.WIMPOD]: EggTier.COMMON, + [Species.SANDYGAST]: EggTier.COMMON, + [Species.PYUKUMUKU]: EggTier.COMMON, + [Species.TYPE_NULL]: EggTier.RARE, + [Species.MINIOR]: EggTier.RARE, + [Species.KOMALA]: EggTier.COMMON, + [Species.TURTONATOR]: EggTier.RARE, + [Species.TOGEDEMARU]: EggTier.COMMON, + [Species.MIMIKYU]: EggTier.RARE, + [Species.BRUXISH]: EggTier.RARE, + [Species.DRAMPA]: EggTier.RARE, + [Species.DHELMISE]: EggTier.RARE, + [Species.JANGMO_O]: EggTier.RARE, + [Species.TAPU_KOKO]: EggTier.EPIC, + [Species.TAPU_LELE]: EggTier.EPIC, + [Species.TAPU_BULU]: EggTier.EPIC, + [Species.TAPU_FINI]: EggTier.EPIC, + [Species.COSMOG]: EggTier.EPIC, + [Species.NIHILEGO]: EggTier.EPIC, + [Species.BUZZWOLE]: EggTier.EPIC, + [Species.PHEROMOSA]: EggTier.EPIC, + [Species.XURKITREE]: EggTier.EPIC, + [Species.CELESTEELA]: EggTier.EPIC, + [Species.KARTANA]: EggTier.EPIC, + [Species.GUZZLORD]: EggTier.EPIC, + [Species.NECROZMA]: EggTier.LEGENDARY, + [Species.MAGEARNA]: EggTier.EPIC, + [Species.MARSHADOW]: EggTier.EPIC, + [Species.POIPOLE]: EggTier.EPIC, + [Species.STAKATAKA]: EggTier.EPIC, + [Species.BLACEPHALON]: EggTier.EPIC, + [Species.ZERAORA]: EggTier.EPIC, + [Species.MELTAN]: EggTier.EPIC, + [Species.ALOLA_RATTATA]: EggTier.COMMON, + [Species.ALOLA_SANDSHREW]: EggTier.COMMON, + [Species.ALOLA_VULPIX]: EggTier.COMMON, + [Species.ALOLA_DIGLETT]: EggTier.COMMON, + [Species.ALOLA_MEOWTH]: EggTier.COMMON, + [Species.ALOLA_GEODUDE]: EggTier.COMMON, + [Species.ALOLA_GRIMER]: EggTier.COMMON, + + [Species.GROOKEY]: EggTier.COMMON, + [Species.SCORBUNNY]: EggTier.RARE, + [Species.SOBBLE]: EggTier.COMMON, + [Species.SKWOVET]: EggTier.COMMON, + [Species.ROOKIDEE]: EggTier.COMMON, + [Species.BLIPBUG]: EggTier.COMMON, + [Species.NICKIT]: EggTier.COMMON, + [Species.GOSSIFLEUR]: EggTier.COMMON, + [Species.WOOLOO]: EggTier.COMMON, + [Species.CHEWTLE]: EggTier.COMMON, + [Species.YAMPER]: EggTier.COMMON, + [Species.ROLYCOLY]: EggTier.COMMON, + [Species.APPLIN]: EggTier.COMMON, + [Species.SILICOBRA]: EggTier.COMMON, + [Species.CRAMORANT]: EggTier.COMMON, + [Species.ARROKUDA]: EggTier.COMMON, + [Species.TOXEL]: EggTier.COMMON, + [Species.SIZZLIPEDE]: EggTier.COMMON, + [Species.CLOBBOPUS]: EggTier.COMMON, + [Species.SINISTEA]: EggTier.COMMON, + [Species.HATENNA]: EggTier.COMMON, + [Species.IMPIDIMP]: EggTier.COMMON, + [Species.MILCERY]: EggTier.COMMON, + [Species.FALINKS]: EggTier.RARE, + [Species.PINCURCHIN]: EggTier.COMMON, + [Species.SNOM]: EggTier.COMMON, + [Species.STONJOURNER]: EggTier.COMMON, + [Species.EISCUE]: EggTier.COMMON, + [Species.INDEEDEE]: EggTier.RARE, + [Species.MORPEKO]: EggTier.COMMON, + [Species.CUFANT]: EggTier.COMMON, + [Species.DRACOZOLT]: EggTier.RARE, + [Species.ARCTOZOLT]: EggTier.RARE, + [Species.DRACOVISH]: EggTier.RARE, + [Species.ARCTOVISH]: EggTier.RARE, + [Species.DURALUDON]: EggTier.RARE, + [Species.DREEPY]: EggTier.RARE, + [Species.ZACIAN]: EggTier.LEGENDARY, + [Species.ZAMAZENTA]: EggTier.LEGENDARY, + [Species.ETERNATUS]: EggTier.COMMON, + [Species.KUBFU]: EggTier.EPIC, + [Species.ZARUDE]: EggTier.EPIC, + [Species.REGIELEKI]: EggTier.EPIC, + [Species.REGIDRAGO]: EggTier.EPIC, + [Species.GLASTRIER]: EggTier.EPIC, + [Species.SPECTRIER]: EggTier.EPIC, + [Species.CALYREX]: EggTier.LEGENDARY, + [Species.GALAR_MEOWTH]: EggTier.COMMON, + [Species.GALAR_PONYTA]: EggTier.COMMON, + [Species.GALAR_SLOWPOKE]: EggTier.COMMON, + [Species.GALAR_FARFETCHD]: EggTier.COMMON, + [Species.GALAR_CORSOLA]: EggTier.COMMON, + [Species.GALAR_ZIGZAGOON]: EggTier.COMMON, + [Species.GALAR_DARUMAKA]: EggTier.RARE, + [Species.GALAR_YAMASK]: EggTier.COMMON, + [Species.GALAR_STUNFISK]: EggTier.COMMON, + [Species.GALAR_MR_MIME]: EggTier.COMMON, + [Species.GALAR_ARTICUNO]: EggTier.EPIC, + [Species.GALAR_ZAPDOS]: EggTier.EPIC, + [Species.GALAR_MOLTRES]: EggTier.EPIC, + [Species.HISUI_GROWLITHE]: EggTier.RARE, + [Species.HISUI_VOLTORB]: EggTier.COMMON, + [Species.HISUI_QWILFISH]: EggTier.RARE, + [Species.HISUI_SNEASEL]: EggTier.RARE, + [Species.HISUI_ZORUA]: EggTier.COMMON, + [Species.ENAMORUS]: EggTier.EPIC, + + [Species.SPRIGATITO]: EggTier.RARE, + [Species.FUECOCO]: EggTier.RARE, + [Species.QUAXLY]: EggTier.RARE, + [Species.LECHONK]: EggTier.COMMON, + [Species.TAROUNTULA]: EggTier.COMMON, + [Species.NYMBLE]: EggTier.COMMON, + [Species.PAWMI]: EggTier.COMMON, + [Species.TANDEMAUS]: EggTier.RARE, + [Species.FIDOUGH]: EggTier.COMMON, + [Species.SMOLIV]: EggTier.COMMON, + [Species.SQUAWKABILLY]: EggTier.COMMON, + [Species.NACLI]: EggTier.RARE, + [Species.CHARCADET]: EggTier.RARE, + [Species.TADBULB]: EggTier.COMMON, + [Species.WATTREL]: EggTier.COMMON, + [Species.MASCHIFF]: EggTier.COMMON, + [Species.SHROODLE]: EggTier.COMMON, + [Species.BRAMBLIN]: EggTier.COMMON, + [Species.TOEDSCOOL]: EggTier.COMMON, + [Species.KLAWF]: EggTier.COMMON, + [Species.CAPSAKID]: EggTier.COMMON, + [Species.RELLOR]: EggTier.COMMON, + [Species.FLITTLE]: EggTier.COMMON, + [Species.TINKATINK]: EggTier.RARE, + [Species.WIGLETT]: EggTier.COMMON, + [Species.BOMBIRDIER]: EggTier.COMMON, + [Species.FINIZEN]: EggTier.COMMON, + [Species.VAROOM]: EggTier.RARE, + [Species.CYCLIZAR]: EggTier.RARE, + [Species.ORTHWORM]: EggTier.RARE, + [Species.GLIMMET]: EggTier.RARE, + [Species.GREAVARD]: EggTier.COMMON, + [Species.FLAMIGO]: EggTier.RARE, + [Species.CETODDLE]: EggTier.COMMON, + [Species.VELUZA]: EggTier.RARE, + [Species.DONDOZO]: EggTier.RARE, + [Species.TATSUGIRI]: EggTier.RARE, + [Species.GREAT_TUSK]: EggTier.EPIC, + [Species.SCREAM_TAIL]: EggTier.EPIC, + [Species.BRUTE_BONNET]: EggTier.EPIC, + [Species.FLUTTER_MANE]: EggTier.EPIC, + [Species.SLITHER_WING]: EggTier.EPIC, + [Species.SANDY_SHOCKS]: EggTier.EPIC, + [Species.IRON_TREADS]: EggTier.EPIC, + [Species.IRON_BUNDLE]: EggTier.EPIC, + [Species.IRON_HANDS]: EggTier.EPIC, + [Species.IRON_JUGULIS]: EggTier.EPIC, + [Species.IRON_MOTH]: EggTier.EPIC, + [Species.IRON_THORNS]: EggTier.EPIC, + [Species.FRIGIBAX]: EggTier.RARE, + [Species.GIMMIGHOUL]: EggTier.RARE, + [Species.WO_CHIEN]: EggTier.EPIC, + [Species.CHIEN_PAO]: EggTier.EPIC, + [Species.TING_LU]: EggTier.EPIC, + [Species.CHI_YU]: EggTier.EPIC, + [Species.ROARING_MOON]: EggTier.EPIC, + [Species.IRON_VALIANT]: EggTier.EPIC, + [Species.KORAIDON]: EggTier.LEGENDARY, + [Species.MIRAIDON]: EggTier.LEGENDARY, + [Species.WALKING_WAKE]: EggTier.EPIC, + [Species.IRON_LEAVES]: EggTier.EPIC, + [Species.POLTCHAGEIST]: EggTier.RARE, + [Species.OKIDOGI]: EggTier.EPIC, + [Species.MUNKIDORI]: EggTier.EPIC, + [Species.FEZANDIPITI]: EggTier.EPIC, + [Species.OGERPON]: EggTier.EPIC, + [Species.GOUGING_FIRE]: EggTier.EPIC, + [Species.RAGING_BOLT]: EggTier.EPIC, + [Species.IRON_BOULDER]: EggTier.EPIC, + [Species.IRON_CROWN]: EggTier.EPIC, + [Species.TERAPAGOS]: EggTier.LEGENDARY, + [Species.PECHARUNT]: EggTier.EPIC, + [Species.PALDEA_TAUROS]: EggTier.RARE, + [Species.PALDEA_WOOPER]: EggTier.COMMON, + [Species.BLOODMOON_URSALUNA]: EggTier.EPIC, +}; diff --git a/src/data/balance/starters.ts b/src/data/balance/starters.ts index 5117f800086..d6a1f0c3eaf 100644 --- a/src/data/balance/starters.ts +++ b/src/data/balance/starters.ts @@ -2,6 +2,12 @@ import { Species } from "#enums/species"; export const POKERUS_STARTER_COUNT = 5; +// #region Friendship constants +export const CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER = 2; +export const FRIENDSHIP_GAIN_FROM_BATTLE = 2; +export const FRIENDSHIP_GAIN_FROM_RARE_CANDY = 5; +export const FRIENDSHIP_LOSS_FROM_FAINT = 10; + /** * Function to get the cumulative friendship threshold at which a candy is earned * @param starterCost The cost of the starter, found in {@linkcode speciesStarterCosts} @@ -9,25 +15,25 @@ export const POKERUS_STARTER_COUNT = 5; */ export function getStarterValueFriendshipCap(starterCost: number): number { switch (starterCost) { - case 1: - return 20; - case 2: - return 40; - case 3: - return 60; - case 4: - return 100; - case 5: - return 140; - case 6: - return 200; - case 7: - return 280; - case 8: - case 9: - return 450; - default: - return 600; + case 1: + return 20; + case 2: + return 40; + case 3: + return 60; + case 4: + return 100; + case 5: + return 140; + case 6: + return 200; + case 7: + return 280; + case 8: + case 9: + return 450; + default: + return 600; } } @@ -630,16 +636,16 @@ export const speciesStarterCosts = { }; const starterCandyCosts: { passive: number; costReduction: [number, number]; egg: number; }[] = [ - { passive: 40, costReduction: [25, 60], egg: 30 }, // 1 Cost - { passive: 40, costReduction: [25, 60], egg: 30 }, // 2 Cost - { passive: 35, costReduction: [20, 50], egg: 25 }, // 3 Cost - { passive: 30, costReduction: [15, 40], egg: 20 }, // 4 Cost - { passive: 25, costReduction: [12, 35], egg: 18 }, // 5 Cost - { passive: 20, costReduction: [10, 30], egg: 15 }, // 6 Cost - { passive: 15, costReduction: [8, 20], egg: 12 }, // 7 Cost - { passive: 10, costReduction: [5, 15], egg: 10 }, // 8 Cost - { passive: 10, costReduction: [5, 15], egg: 10 }, // 9 Cost - { passive: 10, costReduction: [5, 15], egg: 10 }, // 10 Cost + { passive: 40, costReduction: [ 25, 60 ], egg: 30 }, // 1 Cost + { passive: 40, costReduction: [ 25, 60 ], egg: 30 }, // 2 Cost + { passive: 35, costReduction: [ 20, 50 ], egg: 25 }, // 3 Cost + { passive: 30, costReduction: [ 15, 40 ], egg: 20 }, // 4 Cost + { passive: 25, costReduction: [ 12, 35 ], egg: 18 }, // 5 Cost + { passive: 20, costReduction: [ 10, 30 ], egg: 15 }, // 6 Cost + { passive: 15, costReduction: [ 8, 20 ], egg: 12 }, // 7 Cost + { passive: 10, costReduction: [ 5, 15 ], egg: 10 }, // 8 Cost + { passive: 10, costReduction: [ 5, 15 ], egg: 10 }, // 9 Cost + { passive: 10, costReduction: [ 5, 15 ], egg: 10 }, // 10 Cost ]; /** diff --git a/src/data/balance/tms.ts b/src/data/balance/tms.ts index e08b677c30c..1a509637e05 100644 --- a/src/data/balance/tms.ts +++ b/src/data/balance/tms.ts @@ -1107,12 +1107,7 @@ export const tmSpecies: TmSpecies = { Species.QUILLADIN, Species.CHESNAUGHT, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.BUNNELBY, Species.DIGGERSBY, Species.FLETCHLING, @@ -2878,12 +2873,7 @@ export const tmSpecies: TmSpecies = { Species.DELPHOX, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.BUNNELBY, Species.DIGGERSBY, Species.FLETCHLING, @@ -3910,7 +3900,6 @@ export const tmSpecies: TmSpecies = { Species.YAMPER, Species.BOLTUND, Species.ZAMAZENTA, - Species.URSHIFU, Species.ZARUDE, Species.GLASTRIER, Species.WYRDEER, @@ -3940,6 +3929,10 @@ export const tmSpecies: TmSpecies = { Species.ALOLA_NINETALES, Species.ALOLA_PERSIAN, Species.ALOLA_GOLEM, + [ + Species.URSHIFU, + "single-strike", + ], Species.HISUI_GROWLITHE, Species.HISUI_ARCANINE, Species.HISUI_TYPHLOSION, @@ -6987,14 +6980,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -8301,7 +8287,6 @@ export const tmSpecies: TmSpecies = { [ Species.WORMADAM, "sandy", - "trash", ], Species.ALOLA_SANDSHREW, Species.ALOLA_SANDSLASH, @@ -8612,12 +8597,7 @@ export const tmSpecies: TmSpecies = { Species.CHESNAUGHT, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.BUNNELBY, Species.DIGGERSBY, Species.LITLEO, @@ -9406,14 +9386,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -9766,14 +9739,7 @@ export const tmSpecies: TmSpecies = { Species.DELPHOX, Species.VIVILLON, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.ESPURR, Species.MEOWSTIC, @@ -11147,14 +11113,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -13657,12 +13616,7 @@ export const tmSpecies: TmSpecies = { Species.DELPHOX, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.FLETCHLING, Species.FLETCHINDER, Species.TALONFLAME, @@ -15326,14 +15280,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -16934,14 +16881,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -18483,14 +18423,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -20250,14 +20183,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -21583,12 +21509,7 @@ export const tmSpecies: TmSpecies = { Species.DELPHOX, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.BUNNELBY, Species.DIGGERSBY, Species.LITLEO, @@ -22516,7 +22437,6 @@ export const tmSpecies: TmSpecies = { [ Species.WORMADAM, "sandy", - "trash", ], Species.ALOLA_DIGLETT, Species.ALOLA_DUGTRIO, @@ -22691,14 +22611,7 @@ export const tmSpecies: TmSpecies = { Species.CHESNAUGHT, Species.VIVILLON, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -23402,12 +23315,7 @@ export const tmSpecies: TmSpecies = { Species.DELPHOX, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.BUNNELBY, Species.DIGGERSBY, Species.FLETCHLING, @@ -24134,12 +24042,7 @@ export const tmSpecies: TmSpecies = { Species.KELDEO, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.PANCHAM, Species.PANGORO, Species.HONEDGE, @@ -24842,14 +24745,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -25712,14 +25608,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -26695,14 +26584,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -27845,14 +27727,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -28911,14 +28786,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -29514,14 +29382,7 @@ export const tmSpecies: TmSpecies = { Species.DELPHOX, Species.VIVILLON, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.ESPURR, Species.MEOWSTIC, @@ -31408,14 +31269,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -32327,14 +32181,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -33037,14 +32884,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -33471,7 +33311,6 @@ export const tmSpecies: TmSpecies = { Species.ARCTOVISH, Species.ZACIAN, Species.ZAMAZENTA, - Species.URSHIFU, Species.ZARUDE, Species.REGIDRAGO, Species.GLASTRIER, @@ -33522,6 +33361,10 @@ export const tmSpecies: TmSpecies = { Species.ALOLA_MUK, Species.GALAR_MEOWTH, Species.GALAR_STUNFISK, + [ + Species.URSHIFU, + "single-strike", + ], [ Species.CALYREX, "ice", @@ -36644,14 +36487,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -37389,14 +37225,7 @@ export const tmSpecies: TmSpecies = { Species.BUNNELBY, Species.DIGGERSBY, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -38266,23 +38095,11 @@ export const tmSpecies: TmSpecies = { Species.DELPHOX, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -39323,12 +39140,7 @@ export const tmSpecies: TmSpecies = { Species.CHESPIN, Species.QUILLADIN, Species.CHESNAUGHT, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.BUNNELBY, Species.DIGGERSBY, Species.SKIDDO, @@ -40356,7 +40168,10 @@ export const tmSpecies: TmSpecies = { Species.FENNEKIN, Species.BRAIXEN, Species.DELPHOX, - Species.MEOWSTIC, + [ + Species.MEOWSTIC, + "male", + ], Species.KLEFKI, Species.PHANTUMP, Species.TREVENANT, @@ -41805,7 +41620,6 @@ export const tmSpecies: TmSpecies = { [ Species.WORMADAM, "sandy", - "trash", ], Species.ALOLA_SANDSHREW, Species.ALOLA_SANDSLASH, @@ -43701,12 +43515,7 @@ export const tmSpecies: TmSpecies = { Species.DELPHOX, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.BUNNELBY, Species.DIGGERSBY, Species.SKIDDO, @@ -44160,14 +43969,7 @@ export const tmSpecies: TmSpecies = { Species.QUILLADIN, Species.CHESNAUGHT, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -44377,14 +44179,7 @@ export const tmSpecies: TmSpecies = { Species.DELPHOX, Species.VIVILLON, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.ESPURR, Species.MEOWSTIC, @@ -45256,6 +45051,10 @@ export const tmSpecies: TmSpecies = { Species.IRON_CROWN, Species.TERAPAGOS, Species.ALOLA_EXEGGUTOR, + [ + Species.INDEEDEE, + "male", + ], ], [Moves.GYRO_BALL]: [ Species.SQUIRTLE, @@ -47501,12 +47300,7 @@ export const tmSpecies: TmSpecies = { Species.ACCELGOR, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.SKRELP, Species.DRAGALGE, Species.MAREANIE, @@ -48143,7 +47937,6 @@ export const tmSpecies: TmSpecies = { Species.RUNERIGUS, Species.MORPEKO, Species.DURALUDON, - Species.URSHIFU, Species.ZARUDE, Species.SPECTRIER, Species.OVERQWIL, @@ -48179,6 +47972,10 @@ export const tmSpecies: TmSpecies = { Species.GALAR_WEEZING, Species.GALAR_MOLTRES, Species.GALAR_YAMASK, + [ + Species.URSHIFU, + "single-strike", + ], [ Species.CALYREX, "shadow", @@ -48456,14 +48253,7 @@ export const tmSpecies: TmSpecies = { Species.QUILLADIN, Species.CHESNAUGHT, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -49622,7 +49412,10 @@ export const tmSpecies: TmSpecies = { Species.TORTERRA, Species.BUDEW, Species.ROSERADE, - Species.WORMADAM, + [ + Species.WORMADAM, + "plant", + ], Species.MOTHIM, Species.CHERUBI, Species.CHERRIM, @@ -49698,14 +49491,7 @@ export const tmSpecies: TmSpecies = { Species.CHESNAUGHT, Species.VIVILLON, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -52635,7 +52421,10 @@ export const tmSpecies: TmSpecies = { Species.TORTERRA, Species.BUDEW, Species.ROSERADE, - Species.WORMADAM, + [ + Species.WORMADAM, + "plant", + ], Species.SNOVER, Species.ABOMASNOW, Species.TANGROWTH, @@ -53751,7 +53540,10 @@ export const tmSpecies: TmSpecies = { Species.BIBAREL, Species.BUDEW, Species.ROSERADE, - Species.WORMADAM, + [ + Species.WORMADAM, + "plant", + ], Species.PACHIRISU, Species.CHERUBI, Species.CHERRIM, @@ -53863,14 +53655,7 @@ export const tmSpecies: TmSpecies = { Species.BUNNELBY, Species.DIGGERSBY, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -55590,12 +55375,7 @@ export const tmSpecies: TmSpecies = { Species.CHESPIN, Species.QUILLADIN, Species.CHESNAUGHT, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.PANCHAM, Species.PANGORO, Species.HELIOPTILE, @@ -55877,7 +55657,6 @@ export const tmSpecies: TmSpecies = { Species.MR_RIME, Species.MORPEKO, Species.DURALUDON, - Species.URSHIFU, Species.SPECTRIER, Species.MEOWSCARADA, Species.SQUAWKABILLY, @@ -55918,6 +55697,10 @@ export const tmSpecies: TmSpecies = { Species.GALAR_MOLTRES, Species.GALAR_SLOWKING, Species.GALAR_STUNFISK, + [ + Species.URSHIFU, + "single-strike", + ], [ Species.CALYREX, "shadow", @@ -56577,14 +56360,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -57019,14 +56795,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.PANCHAM, Species.PANGORO, @@ -57354,14 +57123,7 @@ export const tmSpecies: TmSpecies = { Species.BRAIXEN, Species.DELPHOX, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.ESPURR, Species.MEOWSTIC, @@ -58997,7 +58759,6 @@ export const tmSpecies: TmSpecies = { [ Species.WORMADAM, "sandy", - "trash", ], Species.ALOLA_SANDSHREW, Species.ALOLA_SANDSLASH, @@ -60070,7 +59831,6 @@ export const tmSpecies: TmSpecies = { Species.DURALUDON, Species.ZACIAN, Species.ZAMAZENTA, - Species.URSHIFU, Species.ZARUDE, Species.GLASTRIER, Species.SPECTRIER, @@ -60116,6 +59876,10 @@ export const tmSpecies: TmSpecies = { Species.HISUI_ZOROARK, Species.HISUI_BRAVIARY, Species.BLOODMOON_URSALUNA, + [ + Species.URSHIFU, + "single-strike", + ], ], [Moves.PHANTOM_FORCE]: [ Species.HAUNTER, @@ -60446,14 +60210,7 @@ export const tmSpecies: TmSpecies = { Species.QUILLADIN, Species.CHESNAUGHT, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -60529,16 +60286,12 @@ export const tmSpecies: TmSpecies = { Species.WHIMSICOTT, Species.ALOMOMOLA, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, - Species.MEOWSTIC, + [ + Species.MEOWSTIC, + "male", + ], Species.SPRITZEE, Species.AROMATISSE, Species.SYLVEON, @@ -61402,14 +61155,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -61899,14 +61645,7 @@ export const tmSpecies: TmSpecies = { Species.MELOETTA, Species.DELPHOX, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SPRITZEE, Species.AROMATISSE, @@ -62617,7 +62356,6 @@ export const tmSpecies: TmSpecies = { Species.SIRFETCHD, Species.FALINKS, Species.PINCURCHIN, - Species.URSHIFU, Species.ZARUDE, Species.GLASTRIER, Species.TAROUNTULA, @@ -62647,6 +62385,10 @@ export const tmSpecies: TmSpecies = { Species.GALAR_ZAPDOS, Species.GALAR_CORSOLA, Species.GALAR_LINOONE, + [ + Species.URSHIFU, + "single-strike", + ], [ Species.CALYREX, "ice", @@ -63541,12 +63283,7 @@ export const tmSpecies: TmSpecies = { Species.KELDEO, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.INKAY, Species.MALAMAR, Species.BINACLE, @@ -64755,7 +64492,6 @@ export const tmSpecies: TmSpecies = { Species.OBSTAGOON, Species.PERRSERKER, Species.MORPEKO, - Species.URSHIFU, Species.ZARUDE, Species.GLASTRIER, Species.SPECTRIER, @@ -64803,6 +64539,10 @@ export const tmSpecies: TmSpecies = { Species.GALAR_LINOONE, Species.GALAR_DARMANITAN, Species.GALAR_STUNFISK, + [ + Species.URSHIFU, + "single-strike", + ], [ Species.CALYREX, "ice", @@ -65933,12 +65673,7 @@ export const tmSpecies: TmSpecies = { Species.DELPHOX, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.BUNNELBY, Species.DIGGERSBY, Species.FLETCHLING, @@ -65950,14 +65685,7 @@ export const tmSpecies: TmSpecies = { Species.LITLEO, Species.PYROAR, Species.FLABEBE, - [ - Species.FLOETTE, - "red", - "yellow", - "orange", - "blue", - "white", - ], + Species.FLOETTE, Species.FLORGES, Species.SKIDDO, Species.GOGOAT, @@ -66291,6 +66019,13 @@ export const tmSpecies: TmSpecies = { Species.MUNKIDORI, Species.FEZANDIPITI, Species.OGERPON, + Species.ARCHALUDON, + Species.HYDRAPPLE, + Species.GOUGING_FIRE, + Species.RAGING_BOLT, + Species.IRON_BOULDER, + Species.IRON_CROWN, + Species.PECHARUNT, Species.GALAR_MEOWTH, Species.GALAR_SLOWPOKE, Species.GALAR_SLOWBRO, @@ -66429,16 +66164,8 @@ export const tmSpecies: TmSpecies = { Species.PIPLUP, Species.PRINPLUP, Species.EMPOLEON, - [ - Species.SHELLOS, - "east", - "west", - ], - [ - Species.GASTRODON, - "east", - "west", - ], + Species.SHELLOS, + Species.GASTRODON, Species.MISMAGIUS, Species.HAPPINY, Species.SNOVER, @@ -66456,25 +66183,11 @@ export const tmSpecies: TmSpecies = { Species.CUBCHOO, Species.BEARTIC, Species.CRYOGONAL, - [ - Species.TORNADUS, - "incarnate", - "therian", - ], - [ - Species.KYUREM, - "", - "black", - "white", - ], + Species.TORNADUS, + Species.KYUREM, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.SKRELP, Species.DRAGALGE, Species.BERGMITE, @@ -66482,11 +66195,7 @@ export const tmSpecies: TmSpecies = { Species.DIANCIE, Species.PRIMARINA, Species.CRABOMINABLE, - [ - Species.MAGEARNA, - "", - "original", - ], + Species.MAGEARNA, Species.INTELEON, Species.FROSMOTH, Species.EISCUE, @@ -66779,12 +66488,7 @@ export const tmSpecies: TmSpecies = { Species.CHESNAUGHT, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.LITLEO, Species.PYROAR, Species.FLABEBE, @@ -67007,23 +66711,14 @@ export const tmSpecies: TmSpecies = { Species.WEAVILE, Species.GLACEON, Species.FROSLASS, - [ - Species.PALKIA, - "", - "origin", - ], + Species.PALKIA, Species.PHIONE, Species.MANAPHY, Species.ARCEUS, Species.OSHAWOTT, Species.DEWOTT, Species.SAMUROTT, - [ - Species.BASCULIN, - "red-striped", - "blue-striped", - "white-striped", - ], + Species.BASCULIN, Species.MINCCINO, Species.CINCCINO, Species.DUCKLETT, @@ -67036,12 +66731,7 @@ export const tmSpecies: TmSpecies = { Species.KELDEO, Species.FROAKIE, Species.FROGADIER, - [ - Species.GRENINJA, - "", - "battle-bond", - "ash", - ], + Species.GRENINJA, Species.FLABEBE, Species.FLOETTE, Species.FLORGES, @@ -67304,6 +66994,10 @@ export const tmSpecies: TmSpecies = { Species.FEZANDIPITI, Species.ALOLA_RAICHU, Species.ETERNAL_FLOETTE, + [ + Species.INDEEDEE, + "female", + ], ], [Moves.TEMPER_FLARE]: [ Species.CHARMANDER, diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index 62ef8112e6c..03bf0809fa6 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -134,15 +134,15 @@ export class AnimConfig { for (const te of frameTimedEvents[fte]) { let timedEvent: AnimTimedEvent | undefined; switch (te.eventType) { - case "AnimTimedSoundEvent": - timedEvent = new AnimTimedSoundEvent(te.frameIndex, te.resourceName, te); - break; - case "AnimTimedAddBgEvent": - timedEvent = new AnimTimedAddBgEvent(te.frameIndex, te.resourceName, te); - break; - case "AnimTimedUpdateBgEvent": - timedEvent = new AnimTimedUpdateBgEvent(te.frameIndex, te.resourceName, te); - break; + case "AnimTimedSoundEvent": + timedEvent = new AnimTimedSoundEvent(te.frameIndex, te.resourceName, te); + break; + case "AnimTimedAddBgEvent": + timedEvent = new AnimTimedAddBgEvent(te.frameIndex, te.resourceName, te); + break; + case "AnimTimedUpdateBgEvent": + timedEvent = new AnimTimedUpdateBgEvent(te.frameIndex, te.resourceName, te); + break; } timedEvent && timedEvents.push(timedEvent); @@ -243,12 +243,12 @@ class AnimFrame { if (!init) { let target = AnimFrameTarget.GRAPHIC; switch (pattern) { - case -2: - target = AnimFrameTarget.TARGET; - break; - case -1: - target = AnimFrameTarget.USER; - break; + case -2: + target = AnimFrameTarget.TARGET; + break; + case -1: + target = AnimFrameTarget.USER; + break; } this.target = target; this.graphicFrame = pattern >= 0 ? pattern : 0; @@ -556,7 +556,7 @@ function logMissingMoveAnim(move: Moves, ...optionalParams: any[]) { * @param encounterAnim one or more animations to fetch */ export async function initEncounterAnims(scene: BattleScene, encounterAnim: EncounterAnim | EncounterAnim[]): Promise { - const anims = Array.isArray(encounterAnim) ? encounterAnim : [encounterAnim]; + const anims = Array.isArray(encounterAnim) ? encounterAnim : [ encounterAnim ]; const encounterAnimNames = Utils.getEnumKeys(EncounterAnim); const encounterAnimFetches: Promise>[] = []; for (const anim of anims) { @@ -774,9 +774,9 @@ export abstract class BattleAnim { private getGraphicFrameData(scene: BattleScene, frames: AnimFrame[], onSubstitute?: boolean): Map> { const ret: Map> = new Map([ - [AnimFrameTarget.GRAPHIC, new Map() ], - [AnimFrameTarget.USER, new Map() ], - [AnimFrameTarget.TARGET, new Map() ] + [ AnimFrameTarget.GRAPHIC, new Map() ], + [ AnimFrameTarget.USER, new Map() ], + [ AnimFrameTarget.TARGET, new Map() ] ]); const isOppAnim = this.isOppAnim(); @@ -803,23 +803,23 @@ export abstract class BattleAnim { let scaleX = (frame.zoomX / 100) * (!frame.mirror ? 1 : -1); const scaleY = (frame.zoomY / 100); switch (frame.focus) { - case AnimFocus.TARGET: - x += targetInitialX - targetFocusX; - y += (targetInitialY - targetHalfHeight) - targetFocusY; - break; - case AnimFocus.USER: - x += userInitialX - userFocusX; - y += (userInitialY - userHalfHeight) - userFocusY; - break; - case AnimFocus.USER_TARGET: - const point = transformPoint(this.srcLine[0], this.srcLine[1], this.srcLine[2], this.srcLine[3], - this.dstLine[0], this.dstLine[1] - userHalfHeight, this.dstLine[2], this.dstLine[3] - targetHalfHeight, x, y); - x = point[0]; - y = point[1]; - if (frame.target === AnimFrameTarget.GRAPHIC && isReversed(this.srcLine[0], this.srcLine[2], this.dstLine[0], this.dstLine[2])) { - scaleX = scaleX * -1; - } - break; + case AnimFocus.TARGET: + x += targetInitialX - targetFocusX; + y += (targetInitialY - targetHalfHeight) - targetFocusY; + break; + case AnimFocus.USER: + x += userInitialX - userFocusX; + y += (userInitialY - userHalfHeight) - userFocusY; + break; + case AnimFocus.USER_TARGET: + const point = transformPoint(this.srcLine[0], this.srcLine[1], this.srcLine[2], this.srcLine[3], + this.dstLine[0], this.dstLine[1] - userHalfHeight, this.dstLine[2], this.dstLine[3] - targetHalfHeight, x, y); + x = point[0]; + y = point[1]; + if (frame.target === AnimFrameTarget.GRAPHIC && isReversed(this.srcLine[0], this.srcLine[2], this.dstLine[0], this.dstLine[2])) { + scaleX = scaleX * -1; + } + break; } const angle = -frame.angle; const key = frame.target === AnimFrameTarget.GRAPHIC ? g++ : frame.target === AnimFrameTarget.USER ? u++ : t++; @@ -993,44 +993,44 @@ export abstract class BattleAnim { spritePriorities[graphicIndex] = frame.priority; const setSpritePriority = (priority: integer) => { switch (priority) { - case 0: - scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, scene.getNonSwitchedEnemyPokemon() || scene.getNonSwitchedPlayerPokemon()!); // This bang assumes that if (the EnemyPokemon is undefined, then the PlayerPokemon function must return an object), correct assumption? - break; - case 1: - scene.field.moveTo(moveSprite, scene.field.getAll().length - 1); - break; - case 2: - switch (frame.focus) { - case AnimFocus.USER: - if (this.bgSprite) { - scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.bgSprite); - } else { - scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, this.user!); // TODO: is this bang correct? + case 0: + scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, scene.getNonSwitchedEnemyPokemon() || scene.getNonSwitchedPlayerPokemon()!); // This bang assumes that if (the EnemyPokemon is undefined, then the PlayerPokemon function must return an object), correct assumption? + break; + case 1: + scene.field.moveTo(moveSprite, scene.field.getAll().length - 1); + break; + case 2: + switch (frame.focus) { + case AnimFocus.USER: + if (this.bgSprite) { + scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.bgSprite); + } else { + scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, this.user!); // TODO: is this bang correct? + } + break; + case AnimFocus.TARGET: + scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, this.target!); // TODO: is this bang correct? + break; + default: + setSpritePriority(1); + break; } break; - case AnimFocus.TARGET: - scene.field.moveBelow(moveSprite as Phaser.GameObjects.GameObject, this.target!); // TODO: is this bang correct? + case 3: + switch (frame.focus) { + case AnimFocus.USER: + scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.user!); // TODO: is this bang correct? + break; + case AnimFocus.TARGET: + scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.target!); // TODO: is this bang correct? + break; + default: + setSpritePriority(1); + break; + } break; default: setSpritePriority(1); - break; - } - break; - case 3: - switch (frame.focus) { - case AnimFocus.USER: - scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.user!); // TODO: is this bang correct? - break; - case AnimFocus.TARGET: - scene.field.moveAbove(moveSprite as Phaser.GameObjects.GameObject, this.target!); // TODO: is this bang correct? - break; - default: - setSpritePriority(1); - break; - } - break; - default: - setSpritePriority(1); } }; setSpritePriority(frame.priority); @@ -1093,9 +1093,9 @@ export abstract class BattleAnim { private getGraphicFrameDataWithoutTarget(frames: AnimFrame[], targetInitialX: number, targetInitialY: number): Map> { const ret: Map> = new Map([ - [AnimFrameTarget.GRAPHIC, new Map() ], - [AnimFrameTarget.USER, new Map() ], - [AnimFrameTarget.TARGET, new Map() ] + [ AnimFrameTarget.GRAPHIC, new Map() ], + [ AnimFrameTarget.USER, new Map() ], + [ AnimFrameTarget.TARGET, new Map() ] ]); let g = 0; @@ -1396,108 +1396,108 @@ export async function populateAnims() { const fieldName = field.slice(0, field.indexOf(":")); const fieldData = field.slice(fieldName.length + 1, field.lastIndexOf("\n")).trim(); switch (fieldName) { - case "array": - const framesData = fieldData.split(" - - - ").slice(1); - for (let fd = 0; fd < framesData.length; fd++) { - anim.frames.push([]); - const frameData = framesData[fd]; - const focusFramesData = frameData.split(" - - "); - for (let tf = 0; tf < focusFramesData.length; tf++) { - const values = focusFramesData[tf].replace(/ \- /g, "").split("\n"); - const targetFrame = new AnimFrame(parseFloat(values[0]), parseFloat(values[1]), parseFloat(values[2]), parseFloat(values[11]), parseFloat(values[3]), - parseInt(values[4]) === 1, parseInt(values[6]) === 1, parseInt(values[5]), parseInt(values[7]), parseInt(values[8]), parseInt(values[12]), parseInt(values[13]), - parseInt(values[14]), parseInt(values[15]), parseInt(values[16]), parseInt(values[17]), parseInt(values[18]), parseInt(values[19]), - parseInt(values[21]), parseInt(values[22]), parseInt(values[23]), parseInt(values[24]), parseInt(values[20]) === 1, parseInt(values[25]), parseInt(values[26]) as AnimFocus); - anim.frames[fd].push(targetFrame); + case "array": + const framesData = fieldData.split(" - - - ").slice(1); + for (let fd = 0; fd < framesData.length; fd++) { + anim.frames.push([]); + const frameData = framesData[fd]; + const focusFramesData = frameData.split(" - - "); + for (let tf = 0; tf < focusFramesData.length; tf++) { + const values = focusFramesData[tf].replace(/ \- /g, "").split("\n"); + const targetFrame = new AnimFrame(parseFloat(values[0]), parseFloat(values[1]), parseFloat(values[2]), parseFloat(values[11]), parseFloat(values[3]), + parseInt(values[4]) === 1, parseInt(values[6]) === 1, parseInt(values[5]), parseInt(values[7]), parseInt(values[8]), parseInt(values[12]), parseInt(values[13]), + parseInt(values[14]), parseInt(values[15]), parseInt(values[16]), parseInt(values[17]), parseInt(values[18]), parseInt(values[19]), + parseInt(values[21]), parseInt(values[22]), parseInt(values[23]), parseInt(values[24]), parseInt(values[20]) === 1, parseInt(values[25]), parseInt(values[26]) as AnimFocus); + anim.frames[fd].push(targetFrame); + } } - } - break; - case "graphic": - const graphic = fieldData !== "''" ? fieldData : ""; - anim.graphic = graphic.indexOf(".") > -1 - ? graphic.slice(0, fieldData.indexOf(".")) - : graphic; - break; - case "timing": - const timingEntries = fieldData.split("- !ruby/object:PBAnimTiming ").slice(1); - for (let t = 0; t < timingEntries.length; t++) { - const timingData = timingEntries[t].replace(/\n/g, " ").replace(/[ ]{2,}/g, " ").replace(/[a-z]+: ! '', /ig, "").replace(/name: (.*?),/, "name: \"$1\",") - .replace(/flashColor: !ruby\/object:Color { alpha: ([\d\.]+), blue: ([\d\.]+), green: ([\d\.]+), red: ([\d\.]+)}/, "flashRed: $4, flashGreen: $3, flashBlue: $2, flashAlpha: $1"); - const frameIndex = parseInt(/frame: (\d+)/.exec(timingData)![1]); // TODO: is the bang correct? - let resourceName = /name: "(.*?)"/.exec(timingData)![1].replace("''", ""); // TODO: is the bang correct? - const timingType = parseInt(/timingType: (\d)/.exec(timingData)![1]); // TODO: is the bang correct? - let timedEvent: AnimTimedEvent | undefined; - switch (timingType) { - case 0: - if (resourceName && resourceName.indexOf(".") === -1) { - let ext: string | undefined; - [ "wav", "mp3", "m4a" ].every(e => { - if (seNames.indexOf(`${resourceName}.${e}`) > -1) { - ext = e; - return false; + break; + case "graphic": + const graphic = fieldData !== "''" ? fieldData : ""; + anim.graphic = graphic.indexOf(".") > -1 + ? graphic.slice(0, fieldData.indexOf(".")) + : graphic; + break; + case "timing": + const timingEntries = fieldData.split("- !ruby/object:PBAnimTiming ").slice(1); + for (let t = 0; t < timingEntries.length; t++) { + const timingData = timingEntries[t].replace(/\n/g, " ").replace(/[ ]{2,}/g, " ").replace(/[a-z]+: ! '', /ig, "").replace(/name: (.*?),/, "name: \"$1\",") + .replace(/flashColor: !ruby\/object:Color { alpha: ([\d\.]+), blue: ([\d\.]+), green: ([\d\.]+), red: ([\d\.]+)}/, "flashRed: $4, flashGreen: $3, flashBlue: $2, flashAlpha: $1"); + const frameIndex = parseInt(/frame: (\d+)/.exec(timingData)![1]); // TODO: is the bang correct? + let resourceName = /name: "(.*?)"/.exec(timingData)![1].replace("''", ""); // TODO: is the bang correct? + const timingType = parseInt(/timingType: (\d)/.exec(timingData)![1]); // TODO: is the bang correct? + let timedEvent: AnimTimedEvent | undefined; + switch (timingType) { + case 0: + if (resourceName && resourceName.indexOf(".") === -1) { + let ext: string | undefined; + [ "wav", "mp3", "m4a" ].every(e => { + if (seNames.indexOf(`${resourceName}.${e}`) > -1) { + ext = e; + return false; + } + return true; + }); + if (!ext) { + ext = ".wav"; + } + resourceName += `.${ext}`; } - return true; - }); - if (!ext) { - ext = ".wav"; + timedEvent = new AnimTimedSoundEvent(frameIndex, resourceName); + break; + case 1: + timedEvent = new AnimTimedAddBgEvent(frameIndex, resourceName.slice(0, resourceName.indexOf("."))); + break; + case 2: + timedEvent = new AnimTimedUpdateBgEvent(frameIndex, resourceName.slice(0, resourceName.indexOf("."))); + break; + } + if (!timedEvent) { + continue; + } + const propPattern = /([a-z]+): (.*?)(?:,|\})/ig; + let propMatch: RegExpExecArray; + while ((propMatch = propPattern.exec(timingData)!)) { // TODO: is this bang correct? + const prop = propMatch[1]; + let value: any = propMatch[2]; + switch (prop) { + case "bgX": + case "bgY": + value = parseFloat(value); + break; + case "volume": + case "pitch": + case "opacity": + case "colorRed": + case "colorGreen": + case "colorBlue": + case "colorAlpha": + case "duration": + case "flashScope": + case "flashRed": + case "flashGreen": + case "flashBlue": + case "flashAlpha": + case "flashDuration": + value = parseInt(value); + break; + } + if (timedEvent.hasOwnProperty(prop)) { + timedEvent[prop] = value; } - resourceName += `.${ext}`; } - timedEvent = new AnimTimedSoundEvent(frameIndex, resourceName); - break; - case 1: - timedEvent = new AnimTimedAddBgEvent(frameIndex, resourceName.slice(0, resourceName.indexOf("."))); - break; - case 2: - timedEvent = new AnimTimedUpdateBgEvent(frameIndex, resourceName.slice(0, resourceName.indexOf("."))); - break; - } - if (!timedEvent) { - continue; - } - const propPattern = /([a-z]+): (.*?)(?:,|\})/ig; - let propMatch: RegExpExecArray; - while ((propMatch = propPattern.exec(timingData)!)) { // TODO: is this bang correct? - const prop = propMatch[1]; - let value: any = propMatch[2]; - switch (prop) { - case "bgX": - case "bgY": - value = parseFloat(value); - break; - case "volume": - case "pitch": - case "opacity": - case "colorRed": - case "colorGreen": - case "colorBlue": - case "colorAlpha": - case "duration": - case "flashScope": - case "flashRed": - case "flashGreen": - case "flashBlue": - case "flashAlpha": - case "flashDuration": - value = parseInt(value); - break; + if (!anim.frameTimedEvents.has(frameIndex)) { + anim.frameTimedEvents.set(frameIndex, []); } - if (timedEvent.hasOwnProperty(prop)) { - timedEvent[prop] = value; - } - } - if (!anim.frameTimedEvents.has(frameIndex)) { - anim.frameTimedEvents.set(frameIndex, []); - } anim.frameTimedEvents.get(frameIndex)!.push(timedEvent); // TODO: is this bang correct? - } - break; - case "position": - anim.position = parseInt(fieldData); - break; - case "hue": - anim.hue = parseInt(fieldData); - break; + } + break; + case "position": + anim.position = parseInt(fieldData); + break; + case "hue": + anim.hue = parseInt(fieldData); + break; } } } diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 42775775ac4..4977a8da5a9 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -23,6 +23,7 @@ import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import { StatStageChangePhase, StatStageChangeCallback } from "#app/phases/stat-stage-change-phase"; import { PokemonAnimType } from "#app/enums/pokemon-anim-type"; +import BattleScene from "#app/battle-scene"; export enum BattlerTagLapseType { FAINT, @@ -90,6 +91,15 @@ export class BattlerTag { this.sourceMove = source.sourceMove; this.sourceId = source.sourceId; } + + /** + * Helper function that retrieves the source Pokemon object + * @param scene medium to retrieve the source Pokemon + * @returns The source {@linkcode Pokemon} or `null` if none is found + */ + public getSourcePokemon(scene: BattleScene): Pokemon | null { + return this.sourceId ? scene.getPokemonById(this.sourceId) : null; + } } export interface WeatherBattlerTag { @@ -120,7 +130,7 @@ export abstract class MoveRestrictionBattlerTag extends BattlerTag { const phase = pokemon.scene.getCurrentPhase() as MovePhase; const move = phase.move; - if (this.isMoveRestricted(move.moveId)) { + if (this.isMoveRestricted(move.moveId, pokemon)) { if (this.interruptedText(pokemon, move.moveId)) { pokemon.scene.queueMessage(this.interruptedText(pokemon, move.moveId)); } @@ -136,10 +146,11 @@ export abstract class MoveRestrictionBattlerTag extends BattlerTag { /** * Gets whether this tag is restricting a move. * - * @param {Moves} move {@linkcode Moves} ID to check restriction for. - * @returns {boolean} `true` if the move is restricted by this tag, otherwise `false`. + * @param move - {@linkcode Moves} ID to check restriction for. + * @param user - The {@linkcode Pokemon} involved + * @returns `true` if the move is restricted by this tag, otherwise `false`. */ - abstract isMoveRestricted(move: Moves): boolean; + public abstract isMoveRestricted(move: Moves, user?: Pokemon): boolean; /** * Checks if this tag is restricting a move based on a user's decisions during the target selection phase @@ -327,6 +338,16 @@ export class GorillaTacticsTag extends MoveRestrictionBattlerTag { pokemon.setStat(Stat.ATK, pokemon.getStat(Stat.ATK, false) * 1.5, false); } + /** + * Loads the Gorilla Tactics Battler Tag along with its unique class variable moveId + * @override + * @param source Gorilla Tactics' {@linkcode BattlerTag} information + */ + public override loadTag(source: BattlerTag | any): void { + super.loadTag(source); + this.moveId = source.moveId; + } + /** * * @override @@ -363,7 +384,7 @@ export class RechargingTag extends BattlerTag { super.onAdd(pokemon); // Queue a placeholder move for the Pokemon to "use" next turn - pokemon.getMoveQueue().push({ move: Moves.NONE, targets: [] }); + pokemon.getMoveQueue().push({ move: Moves.NONE, targets: []}); } /** Cancels the source's move this turn and queues a "__ must recharge!" message */ @@ -569,7 +590,7 @@ export class InterruptedTag extends BattlerTag { super.onAdd(pokemon); pokemon.getMoveQueue().shift(); - pokemon.pushMoveHistory({move: Moves.NONE, result: MoveResult.OTHER}); + pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.OTHER }); } lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { @@ -898,14 +919,14 @@ export class EncoreTag extends BattlerTag { } switch (repeatableMove.move) { - case Moves.MIMIC: - case Moves.MIRROR_MOVE: - case Moves.TRANSFORM: - case Moves.STRUGGLE: - case Moves.SKETCH: - case Moves.SLEEP_TALK: - case Moves.ENCORE: - return false; + case Moves.MIMIC: + case Moves.MIRROR_MOVE: + case Moves.TRANSFORM: + case Moves.STRUGGLE: + case Moves.SKETCH: + case Moves.SLEEP_TALK: + case Moves.ENCORE: + return false; } if (allMoves[repeatableMove.move].hasAttr(ChargeAttr) && repeatableMove.result === MoveResult.OTHER) { @@ -1376,7 +1397,7 @@ export class ContactStatStageChangeProtectedTag extends DamageProtectedTag { const effectPhase = pokemon.scene.getCurrentPhase(); if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) { const attacker = effectPhase.getPokemon(); - pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, attacker.getBattlerIndex(), true, [ this.stat ], this.levels)); + pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, attacker.getBattlerIndex(), false, [ this.stat ], this.levels)); } } @@ -1620,12 +1641,12 @@ export class HighestStatBoostTag extends AbilityBattlerTag { this.stat = highestStat; switch (this.stat) { - case Stat.SPD: - this.multiplier = 1.5; - break; - default: - this.multiplier = 1.3; - break; + case Stat.SPD: + this.multiplier = 1.5; + break; + default: + this.multiplier = 1.3; + break; } pokemon.scene.queueMessage(i18next.t("battlerTags:highestStatBoostOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), statName: i18next.t(getStatKey(highestStat)) }), null, false, null, true); @@ -1713,7 +1734,12 @@ export class TypeImmuneTag extends BattlerTag { } } -export class MagnetRisenTag extends TypeImmuneTag { +/** + * Battler Tag that lifts the affected Pokemon into the air and provides immunity to Ground type moves. + * @see {@link https://bulbapedia.bulbagarden.net/wiki/Magnet_Rise_(move) | Moves.MAGNET_RISE} + * @see {@link https://bulbapedia.bulbagarden.net/wiki/Telekinesis_(move) | Moves.TELEKINESIS} + */ +export class FloatingTag extends TypeImmuneTag { constructor(tagType: BattlerTagType, sourceMove: Moves) { super(tagType, sourceMove, Type.GROUND, 5); } @@ -1721,13 +1747,17 @@ export class MagnetRisenTag extends TypeImmuneTag { onAdd(pokemon: Pokemon): void { super.onAdd(pokemon); - pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); + if (this.sourceMove === Moves.MAGNET_RISE) { + pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); + } + } onRemove(pokemon: Pokemon): void { super.onRemove(pokemon); - - pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnRemove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); + if (this.sourceMove === Moves.MAGNET_RISE) { + pokemon.scene.queueMessage(i18next.t("battlerTags:magnetRisenOnRemove", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); + } } } @@ -1935,10 +1965,10 @@ export class RoostedTag extends BattlerTag { modifiedTypes = currentTypes.filter(type => type !== Type.NORMAL); modifiedTypes.push(Type.FLYING); } else { - modifiedTypes = [Type.FLYING]; + modifiedTypes = [ Type.FLYING ]; } } else { - modifiedTypes = [...currentTypes]; + modifiedTypes = [ ...currentTypes ]; modifiedTypes.push(Type.FLYING); } pokemon.summonData.types = modifiedTypes; @@ -1958,10 +1988,10 @@ export class RoostedTag extends BattlerTag { if (this.isBaseFlying) { let modifiedTypes: Type[]; if (this.isBasePureFlying && !isCurrentlyDualType) { - modifiedTypes = [Type.NORMAL]; + modifiedTypes = [ Type.NORMAL ]; } else { if (!!pokemon.getTag(RemovedTypeTag) && isOriginallyDualType && !isCurrentlyDualType) { - modifiedTypes = [Type.UNKNOWN]; + modifiedTypes = [ Type.UNKNOWN ]; } else { modifiedTypes = currentTypes.filter(type => type !== Type.FLYING); } @@ -2067,8 +2097,8 @@ export class StockpilingTag extends BattlerTag { super.loadTag(source); this.stockpiledCount = source.stockpiledCount || 0; this.statChangeCounts = { - [ Stat.DEF ]: source.statChangeCounts?.[ Stat.DEF ] ?? 0, - [ Stat.SPDEF ]: source.statChangeCounts?.[ Stat.SPDEF ] ?? 0, + [Stat.DEF]: source.statChangeCounts?.[Stat.DEF] ?? 0, + [Stat.SPDEF]: source.statChangeCounts?.[Stat.SPDEF] ?? 0, }; } @@ -2090,7 +2120,7 @@ export class StockpilingTag extends BattlerTag { // Attempt to increase DEF and SPDEF by one stage, keeping track of successful changes. pokemon.scene.unshiftPhase(new StatStageChangePhase( pokemon.scene, pokemon.getBattlerIndex(), true, - [Stat.SPDEF, Stat.DEF], 1, true, false, true, this.onStatStagesChanged + [ Stat.SPDEF, Stat.DEF ], 1, true, false, true, this.onStatStagesChanged )); } } @@ -2139,6 +2169,10 @@ export class GulpMissileTag extends BattlerTag { return false; } + if (moveEffectPhase.move.getMove().hitsSubstitute(attacker, pokemon)) { + return true; + } + const cancelled = new Utils.BooleanHolder(false); applyAbAttrs(BlockNonDirectDamageAbAttr, attacker, cancelled); @@ -2310,6 +2344,21 @@ export class TarShotTag extends BattlerTag { } } +/** + * Battler Tag implementing the type-changing effect of {@link https://bulbapedia.bulbagarden.net/wiki/Electrify_(move) | Electrify}. + * While this tag is in effect, the afflicted Pokemon's moves are changed to Electric type. + */ +export class ElectrifiedTag extends BattlerTag { + constructor() { + super(BattlerTagType.ELECTRIFIED, BattlerTagLapseType.TURN_END, 1, Moves.ELECTRIFY); + } + + override onAdd(pokemon: Pokemon): void { + // "{pokemonNameWithAffix}'s moves have been electrified!" + pokemon.scene.queueMessage(i18next.t("battlerTags:electrifiedOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); + } +} + /** * Battler Tag that keeps track of how many times the user has Autotomized * Each count of Autotomization reduces the weight by 100kg @@ -2354,7 +2403,7 @@ export class SubstituteTag extends BattlerTag { public sourceInFocus: boolean; constructor(sourceMove: Moves, sourceId: integer) { - super(BattlerTagType.SUBSTITUTE, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE, BattlerTagLapseType.HIT], 0, sourceMove, sourceId, true); + super(BattlerTagType.SUBSTITUTE, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE, BattlerTagLapseType.HIT ], 0, sourceMove, sourceId, true); } /** Sets the Substitute's HP and queues an on-add battle animation that initializes the Substitute's sprite. */ @@ -2378,7 +2427,7 @@ export class SubstituteTag extends BattlerTag { onRemove(pokemon: Pokemon): void { // Only play the animation if the cause of removal isn't from the source's own move if (!this.sourceInFocus) { - pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_REMOVE, [this.sprite]); + pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_REMOVE, [ this.sprite ]); } else { this.sprite.destroy(); } @@ -2387,28 +2436,28 @@ export class SubstituteTag extends BattlerTag { lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { switch (lapseType) { - case BattlerTagLapseType.PRE_MOVE: - this.onPreMove(pokemon); - break; - case BattlerTagLapseType.AFTER_MOVE: - this.onAfterMove(pokemon); - break; - case BattlerTagLapseType.HIT: - this.onHit(pokemon); - break; + case BattlerTagLapseType.PRE_MOVE: + this.onPreMove(pokemon); + break; + case BattlerTagLapseType.AFTER_MOVE: + this.onAfterMove(pokemon); + break; + case BattlerTagLapseType.HIT: + this.onHit(pokemon); + break; } return lapseType !== BattlerTagLapseType.CUSTOM; // only remove this tag on custom lapse } /** Triggers an animation that brings the Pokemon into focus before it uses a move */ onPreMove(pokemon: Pokemon): void { - pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_PRE_MOVE, [this.sprite]); + pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_PRE_MOVE, [ this.sprite ]); this.sourceInFocus = true; } /** Triggers an animation that brings the Pokemon out of focus after it uses a move */ onAfterMove(pokemon: Pokemon): void { - pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_POST_MOVE, [this.sprite]); + pokemon.scene.triggerPokemonBattleAnim(pokemon, PokemonAnimType.SUBSTITUTE_POST_MOVE, [ this.sprite ]); this.sourceInFocus = false; } @@ -2482,8 +2531,6 @@ export class MysteryEncounterPostSummonTag extends BattlerTag { * Torment does not interrupt the move if the move is performed consecutively in the same turn and right after Torment is applied */ export class TormentTag extends MoveRestrictionBattlerTag { - private target: Pokemon; - constructor(sourceId: number) { super(BattlerTagType.TORMENT, BattlerTagLapseType.AFTER_MOVE, 1, Moves.TORMENT, sourceId); } @@ -2495,7 +2542,6 @@ export class TormentTag extends MoveRestrictionBattlerTag { */ override onAdd(pokemon: Pokemon) { super.onAdd(pokemon); - this.target = pokemon; pokemon.scene.queueMessage(i18next.t("battlerTags:tormentOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }), 1500); } @@ -2514,15 +2560,18 @@ export class TormentTag extends MoveRestrictionBattlerTag { * @param {Moves} move the move under investigation * @returns `true` if there is valid consecutive usage | `false` if the moves are different from each other */ - override isMoveRestricted(move: Moves): boolean { - const lastMove = this.target.getLastXMoves(1)[0]; + public override isMoveRestricted(move: Moves, user: Pokemon): boolean { + if (!user) { + return false; + } + const lastMove = user.getLastXMoves(1)[0]; if ( !lastMove ) { return false; } // This checks for locking / momentum moves like Rollout and Hydro Cannon + if the user is under the influence of BattlerTagType.FRENZY // Because Uproar's unique behavior is not implemented, it does not check for Uproar. Torment has been marked as partial in moves.ts const moveObj = allMoves[lastMove.move]; - const isUnaffected = moveObj.hasAttr(ConsecutiveUseDoublePowerAttr) || this.target.getTag(BattlerTagType.FRENZY) || moveObj.hasAttr(ChargeAttr); + const isUnaffected = moveObj.hasAttr(ConsecutiveUseDoublePowerAttr) || user.getTag(BattlerTagType.FRENZY) || moveObj.hasAttr(ChargeAttr); const validLastMoveResult = (lastMove.result === MoveResult.SUCCESS) || (lastMove.result === MoveResult.MISS); if (lastMove.move === move && validLastMoveResult && lastMove.move !== Moves.STRUGGLE && !isUnaffected) { return true; @@ -2542,7 +2591,7 @@ export class TormentTag extends MoveRestrictionBattlerTag { */ export class TauntTag extends MoveRestrictionBattlerTag { constructor() { - super(BattlerTagType.TAUNT, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE], 4, Moves.TAUNT); + super(BattlerTagType.TAUNT, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 4, Moves.TAUNT); } override onAdd(pokemon: Pokemon) { @@ -2574,37 +2623,39 @@ export class TauntTag extends MoveRestrictionBattlerTag { * The tag is only removed when the source-user is removed from the field. */ export class ImprisonTag extends MoveRestrictionBattlerTag { - private source: Pokemon | null; - constructor(sourceId: number) { - super(BattlerTagType.IMPRISON, [BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE], 1, Moves.IMPRISON, sourceId); - } - - override onAdd(pokemon: Pokemon) { - if (this.sourceId) { - this.source = pokemon.scene.getPokemonById(this.sourceId); - } + super(BattlerTagType.IMPRISON, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 1, Moves.IMPRISON, sourceId); } /** * Checks if the source of Imprison is still active - * @param _pokemon - * @param _lapseType + * @override + * @param pokemon The pokemon this tag is attached to * @returns `true` if the source is still active */ - override lapse(_pokemon: Pokemon, _lapseType: BattlerTagLapseType): boolean { - return this.source?.isActive(true) ?? false; + public override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { + const source = this.getSourcePokemon(pokemon.scene); + if (source) { + if (lapseType === BattlerTagLapseType.PRE_MOVE) { + return super.lapse(pokemon, lapseType) && source.isActive(true); + } else { + return source.isActive(true); + } + } + return false; } /** * Checks if the source of the tag has the parameter move in its moveset and that the source is still active + * @override * @param {Moves} move the move under investigation * @returns `false` if either condition is not met */ - override isMoveRestricted(move: Moves): boolean { - if (this.source) { - const sourceMoveset = this.source.getMoveset().map(m => m!.moveId); - return sourceMoveset?.includes(move) && this.source.isActive(true); + public override isMoveRestricted(move: Moves, user: Pokemon): boolean { + const source = this.getSourcePokemon(user.scene); + if (source) { + const sourceMoveset = source.getMoveset().map(m => m!.moveId); + return sourceMoveset?.includes(move) && source.isActive(true); } return false; } @@ -2621,16 +2672,16 @@ export class ImprisonTag extends MoveRestrictionBattlerTag { /** * Battler Tag that applies the effects of Syrup Bomb to the target Pokemon. * For three turns, starting from the turn of hit, at the end of each turn, the target Pokemon's speed will decrease by 1. - * The tag can also expire by taking the target Pokemon off the field. + * The tag can also expire by taking the target Pokemon off the field, or the Pokemon that originally used the move. */ export class SyrupBombTag extends BattlerTag { - constructor() { - super(BattlerTagType.SYRUP_BOMB, BattlerTagLapseType.TURN_END, 3, Moves.SYRUP_BOMB); + constructor(sourceId: number) { + super(BattlerTagType.SYRUP_BOMB, BattlerTagLapseType.TURN_END, 3, Moves.SYRUP_BOMB, sourceId); } /** * Adds the Syrup Bomb battler tag to the target Pokemon. - * @param {Pokemon} pokemon the target Pokemon + * @param pokemon - The target {@linkcode Pokemon} */ override onAdd(pokemon: Pokemon) { super.onAdd(pokemon); @@ -2639,201 +2690,258 @@ export class SyrupBombTag extends BattlerTag { /** * Applies the single-stage speed down to the target Pokemon and decrements the tag's turn count - * @param {Pokemon} pokemon the target Pokemon - * @param {BattlerTagLapseType} _lapseType - * @returns `true` if the turnCount is still greater than 0 | `false` if the turnCount is 0 or the target Pokemon has been removed from the field + * @param pokemon - The target {@linkcode Pokemon} + * @param _lapseType - N/A + * @returns `true` if the `turnCount` is still greater than `0`; `false` if the `turnCount` is `0` or the target or source Pokemon has been removed from the field */ override lapse(pokemon: Pokemon, _lapseType: BattlerTagLapseType): boolean { - if (!pokemon.isActive(true)) { + if (this.sourceId && !pokemon.scene.getPokemonById(this.sourceId)?.isActive(true)) { return false; } - pokemon.scene.queueMessage(i18next.t("battlerTags:syrupBombLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); // Custom message in lieu of an animation in mainline + // Custom message in lieu of an animation in mainline + pokemon.scene.queueMessage(i18next.t("battlerTags:syrupBombLapse", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); pokemon.scene.unshiftPhase(new StatStageChangePhase( pokemon.scene, pokemon.getBattlerIndex(), true, - [Stat.SPD], -1, true, false, true + [ Stat.SPD ], -1, true, false, true )); return --this.turnCount > 0; } } +/** + * Telekinesis raises the target into the air for three turns and causes all moves used against the target (aside from OHKO moves) to hit the target unless the target is in a semi-invulnerable state from Fly/Dig. + * The first effect is provided by {@linkcode FloatingTag}, the accuracy-bypass effect is provided by TelekinesisTag + * The effects of Telekinesis can be baton passed to a teammate. Unlike the mainline games, Telekinesis can be baton-passed to Mega Gengar. + * @see {@link https://bulbapedia.bulbagarden.net/wiki/Telekinesis_(move) | Moves.TELEKINESIS} + */ +export class TelekinesisTag extends BattlerTag { + constructor(sourceMove: Moves) { + super(BattlerTagType.TELEKINESIS, [ BattlerTagLapseType.PRE_MOVE, BattlerTagLapseType.AFTER_MOVE ], 3, sourceMove, undefined, true); + } + + override onAdd(pokemon: Pokemon) { + pokemon.scene.queueMessage(i18next.t("battlerTags:telekinesisOnAdd", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); + } +} + +/** + * Tag that swaps the user's base ATK stat with its base DEF stat. + * @extends BattlerTag + */ +export class PowerTrickTag extends BattlerTag { + constructor(sourceMove: Moves, sourceId: number) { + super(BattlerTagType.POWER_TRICK, BattlerTagLapseType.CUSTOM, 0, sourceMove, sourceId, true); + } + + onAdd(pokemon: Pokemon): void { + this.swapStat(pokemon); + pokemon.scene.queueMessage(i18next.t("battlerTags:powerTrickActive", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); + } + + onRemove(pokemon: Pokemon): void { + this.swapStat(pokemon); + pokemon.scene.queueMessage(i18next.t("battlerTags:powerTrickActive", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) })); + } + + /** + * Removes the Power Trick tag and reverts any stat changes if the tag is already applied. + * @param {Pokemon} pokemon The {@linkcode Pokemon} that already has the Power Trick tag. + */ + onOverlap(pokemon: Pokemon): void { + pokemon.removeTag(this.tagType); + } + + /** + * Swaps the user's base ATK stat with its base DEF stat. + * @param {Pokemon} pokemon The {@linkcode Pokemon} whose stats will be swapped. + */ + swapStat(pokemon: Pokemon): void { + const temp = pokemon.getStat(Stat.ATK, false); + pokemon.setStat(Stat.ATK, pokemon.getStat(Stat.DEF, false), false); + pokemon.setStat(Stat.DEF, temp, false); + } +} + /** * Retrieves a {@linkcode BattlerTag} based on the provided tag type, turn count, source move, and source ID. - * - * @param {BattlerTagType} tagType the type of the {@linkcode BattlerTagType}. - * @param turnCount the turn count. - * @param {Moves} sourceMove the source {@linkcode Moves}. - * @param sourceId the source ID. - * @returns {BattlerTag} the corresponding {@linkcode BattlerTag} object. + * @param sourceId - The ID of the pokemon adding the tag + * @returns The corresponding {@linkcode BattlerTag} object. */ export function getBattlerTag(tagType: BattlerTagType, turnCount: number, sourceMove: Moves, sourceId: number): BattlerTag { switch (tagType) { - case BattlerTagType.RECHARGING: - return new RechargingTag(sourceMove); - case BattlerTagType.BEAK_BLAST_CHARGING: - return new BeakBlastChargingTag(); - case BattlerTagType.SHELL_TRAP: - return new ShellTrapTag(); - case BattlerTagType.FLINCHED: - return new FlinchedTag(sourceMove); - case BattlerTagType.INTERRUPTED: - return new InterruptedTag(sourceMove); - case BattlerTagType.CONFUSED: - return new ConfusedTag(turnCount, sourceMove); - case BattlerTagType.INFATUATED: - return new InfatuatedTag(sourceMove, sourceId); - case BattlerTagType.SEEDED: - return new SeedTag(sourceId); - case BattlerTagType.NIGHTMARE: - return new NightmareTag(); - case BattlerTagType.FRENZY: - return new FrenzyTag(turnCount, sourceMove, sourceId); - case BattlerTagType.CHARGING: - return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, 1, sourceMove, sourceId); - case BattlerTagType.ENCORE: - return new EncoreTag(sourceId); - case BattlerTagType.HELPING_HAND: - return new HelpingHandTag(sourceId); - case BattlerTagType.INGRAIN: - return new IngrainTag(sourceId); - case BattlerTagType.AQUA_RING: - return new AquaRingTag(); - case BattlerTagType.DROWSY: - return new DrowsyTag(); - case BattlerTagType.TRAPPED: - return new TrappedTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); - case BattlerTagType.NO_RETREAT: - return new NoRetreatTag(sourceId); - case BattlerTagType.BIND: - return new BindTag(turnCount, sourceId); - case BattlerTagType.WRAP: - return new WrapTag(turnCount, sourceId); - case BattlerTagType.FIRE_SPIN: - return new FireSpinTag(turnCount, sourceId); - case BattlerTagType.WHIRLPOOL: - return new WhirlpoolTag(turnCount, sourceId); - case BattlerTagType.CLAMP: - return new ClampTag(turnCount, sourceId); - case BattlerTagType.SAND_TOMB: - return new SandTombTag(turnCount, sourceId); - case BattlerTagType.MAGMA_STORM: - return new MagmaStormTag(turnCount, sourceId); - case BattlerTagType.SNAP_TRAP: - return new SnapTrapTag(turnCount, sourceId); - case BattlerTagType.THUNDER_CAGE: - return new ThunderCageTag(turnCount, sourceId); - case BattlerTagType.INFESTATION: - return new InfestationTag(turnCount, sourceId); - case BattlerTagType.PROTECTED: - return new ProtectedTag(sourceMove); - case BattlerTagType.SPIKY_SHIELD: - return new ContactDamageProtectedTag(sourceMove, 8); - case BattlerTagType.KINGS_SHIELD: - return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.ATK, -1); - case BattlerTagType.OBSTRUCT: - return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.DEF, -2); - case BattlerTagType.SILK_TRAP: - return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.SPD, -1); - case BattlerTagType.BANEFUL_BUNKER: - return new ContactPoisonProtectedTag(sourceMove); - case BattlerTagType.BURNING_BULWARK: - return new ContactBurnProtectedTag(sourceMove); - case BattlerTagType.ENDURING: - return new EnduringTag(sourceMove); - case BattlerTagType.STURDY: - return new SturdyTag(sourceMove); - case BattlerTagType.PERISH_SONG: - return new PerishSongTag(turnCount); - case BattlerTagType.CENTER_OF_ATTENTION: - return new CenterOfAttentionTag(sourceMove); - case BattlerTagType.TRUANT: - return new TruantTag(); - case BattlerTagType.SLOW_START: - return new SlowStartTag(); - case BattlerTagType.PROTOSYNTHESIS: - return new WeatherHighestStatBoostTag(tagType, Abilities.PROTOSYNTHESIS, WeatherType.SUNNY, WeatherType.HARSH_SUN); - case BattlerTagType.QUARK_DRIVE: - return new TerrainHighestStatBoostTag(tagType, Abilities.QUARK_DRIVE, TerrainType.ELECTRIC); - case BattlerTagType.FLYING: - case BattlerTagType.UNDERGROUND: - case BattlerTagType.UNDERWATER: - case BattlerTagType.HIDDEN: - return new SemiInvulnerableTag(tagType, turnCount, sourceMove); - case BattlerTagType.FIRE_BOOST: - return new TypeBoostTag(tagType, sourceMove, Type.FIRE, 1.5, false); - case BattlerTagType.CRIT_BOOST: - return new CritBoostTag(tagType, sourceMove); - case BattlerTagType.DRAGON_CHEER: - return new DragonCheerTag(); - case BattlerTagType.ALWAYS_CRIT: - case BattlerTagType.IGNORE_ACCURACY: - return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, 2, sourceMove); - case BattlerTagType.ALWAYS_GET_HIT: - case BattlerTagType.RECEIVE_DOUBLE_DAMAGE: - return new BattlerTag(tagType, BattlerTagLapseType.PRE_MOVE, 1, sourceMove); - case BattlerTagType.BYPASS_SLEEP: - return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove); - case BattlerTagType.IGNORE_FLYING: - return new GroundedTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove); - case BattlerTagType.ROOSTED: - return new RoostedTag(); - case BattlerTagType.BURNED_UP: - return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove); - case BattlerTagType.DOUBLE_SHOCKED: - return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove); - case BattlerTagType.SALT_CURED: - return new SaltCuredTag(sourceId); - case BattlerTagType.CURSED: - return new CursedTag(sourceId); - case BattlerTagType.CHARGED: - return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true); - case BattlerTagType.MAGNET_RISEN: - return new MagnetRisenTag(tagType, sourceMove); - case BattlerTagType.MINIMIZED: - return new MinimizeTag(); - case BattlerTagType.DESTINY_BOND: - return new DestinyBondTag(sourceMove, sourceId); - case BattlerTagType.ICE_FACE: - return new IceFaceBlockDamageTag(tagType); - case BattlerTagType.DISGUISE: - return new FormBlockDamageTag(tagType); - case BattlerTagType.STOCKPILING: - return new StockpilingTag(sourceMove); - case BattlerTagType.OCTOLOCK: - return new OctolockTag(sourceId); - case BattlerTagType.DISABLED: - return new DisabledTag(sourceId); - case BattlerTagType.IGNORE_GHOST: - return new ExposedTag(tagType, sourceMove, Type.GHOST, [Type.NORMAL, Type.FIGHTING]); - case BattlerTagType.IGNORE_DARK: - return new ExposedTag(tagType, sourceMove, Type.DARK, [Type.PSYCHIC]); - case BattlerTagType.GULP_MISSILE_ARROKUDA: - case BattlerTagType.GULP_MISSILE_PIKACHU: - return new GulpMissileTag(tagType, sourceMove); - case BattlerTagType.TAR_SHOT: - return new TarShotTag(); - case BattlerTagType.THROAT_CHOPPED: - return new ThroatChoppedTag(); - case BattlerTagType.GORILLA_TACTICS: - return new GorillaTacticsTag(); - case BattlerTagType.SUBSTITUTE: - return new SubstituteTag(sourceMove, sourceId); - case BattlerTagType.AUTOTOMIZED: - return new AutotomizedTag(); - case BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON: - return new MysteryEncounterPostSummonTag(); - case BattlerTagType.HEAL_BLOCK: - return new HealBlockTag(turnCount, sourceMove); - case BattlerTagType.TORMENT: - return new TormentTag(sourceId); - case BattlerTagType.TAUNT: - return new TauntTag(); - case BattlerTagType.IMPRISON: - return new ImprisonTag(sourceId); - case BattlerTagType.SYRUP_BOMB: - return new SyrupBombTag(); - case BattlerTagType.NONE: - default: - return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); + case BattlerTagType.RECHARGING: + return new RechargingTag(sourceMove); + case BattlerTagType.BEAK_BLAST_CHARGING: + return new BeakBlastChargingTag(); + case BattlerTagType.SHELL_TRAP: + return new ShellTrapTag(); + case BattlerTagType.FLINCHED: + return new FlinchedTag(sourceMove); + case BattlerTagType.INTERRUPTED: + return new InterruptedTag(sourceMove); + case BattlerTagType.CONFUSED: + return new ConfusedTag(turnCount, sourceMove); + case BattlerTagType.INFATUATED: + return new InfatuatedTag(sourceMove, sourceId); + case BattlerTagType.SEEDED: + return new SeedTag(sourceId); + case BattlerTagType.NIGHTMARE: + return new NightmareTag(); + case BattlerTagType.FRENZY: + return new FrenzyTag(turnCount, sourceMove, sourceId); + case BattlerTagType.CHARGING: + return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, 1, sourceMove, sourceId); + case BattlerTagType.ENCORE: + return new EncoreTag(sourceId); + case BattlerTagType.HELPING_HAND: + return new HelpingHandTag(sourceId); + case BattlerTagType.INGRAIN: + return new IngrainTag(sourceId); + case BattlerTagType.AQUA_RING: + return new AquaRingTag(); + case BattlerTagType.DROWSY: + return new DrowsyTag(); + case BattlerTagType.TRAPPED: + return new TrappedTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); + case BattlerTagType.NO_RETREAT: + return new NoRetreatTag(sourceId); + case BattlerTagType.BIND: + return new BindTag(turnCount, sourceId); + case BattlerTagType.WRAP: + return new WrapTag(turnCount, sourceId); + case BattlerTagType.FIRE_SPIN: + return new FireSpinTag(turnCount, sourceId); + case BattlerTagType.WHIRLPOOL: + return new WhirlpoolTag(turnCount, sourceId); + case BattlerTagType.CLAMP: + return new ClampTag(turnCount, sourceId); + case BattlerTagType.SAND_TOMB: + return new SandTombTag(turnCount, sourceId); + case BattlerTagType.MAGMA_STORM: + return new MagmaStormTag(turnCount, sourceId); + case BattlerTagType.SNAP_TRAP: + return new SnapTrapTag(turnCount, sourceId); + case BattlerTagType.THUNDER_CAGE: + return new ThunderCageTag(turnCount, sourceId); + case BattlerTagType.INFESTATION: + return new InfestationTag(turnCount, sourceId); + case BattlerTagType.PROTECTED: + return new ProtectedTag(sourceMove); + case BattlerTagType.SPIKY_SHIELD: + return new ContactDamageProtectedTag(sourceMove, 8); + case BattlerTagType.KINGS_SHIELD: + return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.ATK, -1); + case BattlerTagType.OBSTRUCT: + return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.DEF, -2); + case BattlerTagType.SILK_TRAP: + return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.SPD, -1); + case BattlerTagType.BANEFUL_BUNKER: + return new ContactPoisonProtectedTag(sourceMove); + case BattlerTagType.BURNING_BULWARK: + return new ContactBurnProtectedTag(sourceMove); + case BattlerTagType.ENDURING: + return new EnduringTag(sourceMove); + case BattlerTagType.STURDY: + return new SturdyTag(sourceMove); + case BattlerTagType.PERISH_SONG: + return new PerishSongTag(turnCount); + case BattlerTagType.CENTER_OF_ATTENTION: + return new CenterOfAttentionTag(sourceMove); + case BattlerTagType.TRUANT: + return new TruantTag(); + case BattlerTagType.SLOW_START: + return new SlowStartTag(); + case BattlerTagType.PROTOSYNTHESIS: + return new WeatherHighestStatBoostTag(tagType, Abilities.PROTOSYNTHESIS, WeatherType.SUNNY, WeatherType.HARSH_SUN); + case BattlerTagType.QUARK_DRIVE: + return new TerrainHighestStatBoostTag(tagType, Abilities.QUARK_DRIVE, TerrainType.ELECTRIC); + case BattlerTagType.FLYING: + case BattlerTagType.UNDERGROUND: + case BattlerTagType.UNDERWATER: + case BattlerTagType.HIDDEN: + return new SemiInvulnerableTag(tagType, turnCount, sourceMove); + case BattlerTagType.FIRE_BOOST: + return new TypeBoostTag(tagType, sourceMove, Type.FIRE, 1.5, false); + case BattlerTagType.CRIT_BOOST: + return new CritBoostTag(tagType, sourceMove); + case BattlerTagType.DRAGON_CHEER: + return new DragonCheerTag(); + case BattlerTagType.ALWAYS_CRIT: + case BattlerTagType.IGNORE_ACCURACY: + return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, 2, sourceMove); + case BattlerTagType.ALWAYS_GET_HIT: + case BattlerTagType.RECEIVE_DOUBLE_DAMAGE: + return new BattlerTag(tagType, BattlerTagLapseType.PRE_MOVE, 1, sourceMove); + case BattlerTagType.BYPASS_SLEEP: + return new BattlerTag(tagType, BattlerTagLapseType.TURN_END, turnCount, sourceMove); + case BattlerTagType.IGNORE_FLYING: + return new GroundedTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove); + case BattlerTagType.ROOSTED: + return new RoostedTag(); + case BattlerTagType.BURNED_UP: + return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove); + case BattlerTagType.DOUBLE_SHOCKED: + return new RemovedTypeTag(tagType, BattlerTagLapseType.CUSTOM, sourceMove); + case BattlerTagType.SALT_CURED: + return new SaltCuredTag(sourceId); + case BattlerTagType.CURSED: + return new CursedTag(sourceId); + case BattlerTagType.CHARGED: + return new TypeBoostTag(tagType, sourceMove, Type.ELECTRIC, 2, true); + case BattlerTagType.FLOATING: + return new FloatingTag(tagType, sourceMove); + case BattlerTagType.MINIMIZED: + return new MinimizeTag(); + case BattlerTagType.DESTINY_BOND: + return new DestinyBondTag(sourceMove, sourceId); + case BattlerTagType.ICE_FACE: + return new IceFaceBlockDamageTag(tagType); + case BattlerTagType.DISGUISE: + return new FormBlockDamageTag(tagType); + case BattlerTagType.STOCKPILING: + return new StockpilingTag(sourceMove); + case BattlerTagType.OCTOLOCK: + return new OctolockTag(sourceId); + case BattlerTagType.DISABLED: + return new DisabledTag(sourceId); + case BattlerTagType.IGNORE_GHOST: + return new ExposedTag(tagType, sourceMove, Type.GHOST, [ Type.NORMAL, Type.FIGHTING ]); + case BattlerTagType.IGNORE_DARK: + return new ExposedTag(tagType, sourceMove, Type.DARK, [ Type.PSYCHIC ]); + case BattlerTagType.GULP_MISSILE_ARROKUDA: + case BattlerTagType.GULP_MISSILE_PIKACHU: + return new GulpMissileTag(tagType, sourceMove); + case BattlerTagType.TAR_SHOT: + return new TarShotTag(); + case BattlerTagType.ELECTRIFIED: + return new ElectrifiedTag(); + case BattlerTagType.THROAT_CHOPPED: + return new ThroatChoppedTag(); + case BattlerTagType.GORILLA_TACTICS: + return new GorillaTacticsTag(); + case BattlerTagType.SUBSTITUTE: + return new SubstituteTag(sourceMove, sourceId); + case BattlerTagType.AUTOTOMIZED: + return new AutotomizedTag(); + case BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON: + return new MysteryEncounterPostSummonTag(); + case BattlerTagType.HEAL_BLOCK: + return new HealBlockTag(turnCount, sourceMove); + case BattlerTagType.TORMENT: + return new TormentTag(sourceId); + case BattlerTagType.TAUNT: + return new TauntTag(); + case BattlerTagType.IMPRISON: + return new ImprisonTag(sourceId); + case BattlerTagType.SYRUP_BOMB: + return new SyrupBombTag(sourceId); + case BattlerTagType.TELEKINESIS: + return new TelekinesisTag(sourceMove); + case BattlerTagType.POWER_TRICK: + return new PowerTrickTag(sourceMove, sourceId); + case BattlerTagType.NONE: + default: + return new BattlerTag(tagType, BattlerTagLapseType.CUSTOM, turnCount, sourceMove, sourceId); } } diff --git a/src/data/berry.ts b/src/data/berry.ts index 01325ee39dd..7243c4c1b2e 100644 --- a/src/data/berry.ts +++ b/src/data/berry.ts @@ -22,42 +22,42 @@ export type BerryPredicate = (pokemon: Pokemon) => boolean; export function getBerryPredicate(berryType: BerryType): BerryPredicate { switch (berryType) { - case BerryType.SITRUS: - return (pokemon: Pokemon) => pokemon.getHpRatio() < 0.5; - case BerryType.LUM: - return (pokemon: Pokemon) => !!pokemon.status || !!pokemon.getTag(BattlerTagType.CONFUSED); - case BerryType.ENIGMA: - return (pokemon: Pokemon) => !!pokemon.turnData.attacksReceived.filter(a => a.result === HitResult.SUPER_EFFECTIVE).length; - case BerryType.LIECHI: - case BerryType.GANLON: - case BerryType.PETAYA: - case BerryType.APICOT: - case BerryType.SALAC: - return (pokemon: Pokemon) => { - const threshold = new Utils.NumberHolder(0.25); - // Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth - const stat: BattleStat = berryType - BerryType.ENIGMA; - applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); - return pokemon.getHpRatio() < threshold.value && pokemon.getStatStage(stat) < 6; - }; - case BerryType.LANSAT: - return (pokemon: Pokemon) => { - const threshold = new Utils.NumberHolder(0.25); - applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); - return pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST); - }; - case BerryType.STARF: - return (pokemon: Pokemon) => { - const threshold = new Utils.NumberHolder(0.25); - applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); - return pokemon.getHpRatio() < 0.25; - }; - case BerryType.LEPPA: - return (pokemon: Pokemon) => { - const threshold = new Utils.NumberHolder(0.25); - applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); - return !!pokemon.getMoveset().find(m => !m?.getPpRatio()); - }; + case BerryType.SITRUS: + return (pokemon: Pokemon) => pokemon.getHpRatio() < 0.5; + case BerryType.LUM: + return (pokemon: Pokemon) => !!pokemon.status || !!pokemon.getTag(BattlerTagType.CONFUSED); + case BerryType.ENIGMA: + return (pokemon: Pokemon) => !!pokemon.turnData.attacksReceived.filter(a => a.result === HitResult.SUPER_EFFECTIVE).length; + case BerryType.LIECHI: + case BerryType.GANLON: + case BerryType.PETAYA: + case BerryType.APICOT: + case BerryType.SALAC: + return (pokemon: Pokemon) => { + const threshold = new Utils.NumberHolder(0.25); + // Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth + const stat: BattleStat = berryType - BerryType.ENIGMA; + applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); + return pokemon.getHpRatio() < threshold.value && pokemon.getStatStage(stat) < 6; + }; + case BerryType.LANSAT: + return (pokemon: Pokemon) => { + const threshold = new Utils.NumberHolder(0.25); + applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); + return pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST); + }; + case BerryType.STARF: + return (pokemon: Pokemon) => { + const threshold = new Utils.NumberHolder(0.25); + applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); + return pokemon.getHpRatio() < 0.25; + }; + case BerryType.LEPPA: + return (pokemon: Pokemon) => { + const threshold = new Utils.NumberHolder(0.25); + applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); + return !!pokemon.getMoveset().find(m => !m?.getPpRatio()); + }; } } @@ -65,70 +65,70 @@ export type BerryEffectFunc = (pokemon: Pokemon) => void; export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc { switch (berryType) { - case BerryType.SITRUS: - case BerryType.ENIGMA: - return (pokemon: Pokemon) => { - if (pokemon.battleData) { - pokemon.battleData.berriesEaten.push(berryType); - } - const hpHealed = new Utils.NumberHolder(Utils.toDmgValue(pokemon.getMaxHp() / 4)); - applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, hpHealed); - pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), - hpHealed.value, i18next.t("battle:hpHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), berryName: getBerryName(berryType) }), true)); - }; - case BerryType.LUM: - return (pokemon: Pokemon) => { - if (pokemon.battleData) { - pokemon.battleData.berriesEaten.push(berryType); - } - if (pokemon.status) { - pokemon.scene.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon))); - } - pokemon.resetStatus(true, true); - pokemon.updateInfo(); - }; - case BerryType.LIECHI: - case BerryType.GANLON: - case BerryType.PETAYA: - case BerryType.APICOT: - case BerryType.SALAC: - return (pokemon: Pokemon) => { - if (pokemon.battleData) { - pokemon.battleData.berriesEaten.push(berryType); - } - // Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth - const stat: BattleStat = berryType - BerryType.ENIGMA; - const statStages = new Utils.NumberHolder(1); - applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statStages); - pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], statStages.value)); - }; - case BerryType.LANSAT: - return (pokemon: Pokemon) => { - if (pokemon.battleData) { - pokemon.battleData.berriesEaten.push(berryType); - } - pokemon.addTag(BattlerTagType.CRIT_BOOST); - }; - case BerryType.STARF: - return (pokemon: Pokemon) => { - if (pokemon.battleData) { - pokemon.battleData.berriesEaten.push(berryType); - } - const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK); - const stages = new Utils.NumberHolder(2); - applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages); - pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value)); - }; - case BerryType.LEPPA: - return (pokemon: Pokemon) => { - if (pokemon.battleData) { - pokemon.battleData.berriesEaten.push(berryType); - } - const ppRestoreMove = pokemon.getMoveset().find(m => !m?.getPpRatio()) ? pokemon.getMoveset().find(m => !m?.getPpRatio()) : pokemon.getMoveset().find(m => m!.getPpRatio() < 1); // TODO: is this bang correct? - if (ppRestoreMove !== undefined) { + case BerryType.SITRUS: + case BerryType.ENIGMA: + return (pokemon: Pokemon) => { + if (pokemon.battleData) { + pokemon.battleData.berriesEaten.push(berryType); + } + const hpHealed = new Utils.NumberHolder(Utils.toDmgValue(pokemon.getMaxHp() / 4)); + applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, hpHealed); + pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), + hpHealed.value, i18next.t("battle:hpHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), berryName: getBerryName(berryType) }), true)); + }; + case BerryType.LUM: + return (pokemon: Pokemon) => { + if (pokemon.battleData) { + pokemon.battleData.berriesEaten.push(berryType); + } + if (pokemon.status) { + pokemon.scene.queueMessage(getStatusEffectHealText(pokemon.status.effect, getPokemonNameWithAffix(pokemon))); + } + pokemon.resetStatus(true, true); + pokemon.updateInfo(); + }; + case BerryType.LIECHI: + case BerryType.GANLON: + case BerryType.PETAYA: + case BerryType.APICOT: + case BerryType.SALAC: + return (pokemon: Pokemon) => { + if (pokemon.battleData) { + pokemon.battleData.berriesEaten.push(berryType); + } + // Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth + const stat: BattleStat = berryType - BerryType.ENIGMA; + const statStages = new Utils.NumberHolder(1); + applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statStages); + pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], statStages.value)); + }; + case BerryType.LANSAT: + return (pokemon: Pokemon) => { + if (pokemon.battleData) { + pokemon.battleData.berriesEaten.push(berryType); + } + pokemon.addTag(BattlerTagType.CRIT_BOOST); + }; + case BerryType.STARF: + return (pokemon: Pokemon) => { + if (pokemon.battleData) { + pokemon.battleData.berriesEaten.push(berryType); + } + const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK); + const stages = new Utils.NumberHolder(2); + applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages); + pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value)); + }; + case BerryType.LEPPA: + return (pokemon: Pokemon) => { + if (pokemon.battleData) { + pokemon.battleData.berriesEaten.push(berryType); + } + const ppRestoreMove = pokemon.getMoveset().find(m => !m?.getPpRatio()) ? pokemon.getMoveset().find(m => !m?.getPpRatio()) : pokemon.getMoveset().find(m => m!.getPpRatio() < 1); // TODO: is this bang correct? + if (ppRestoreMove !== undefined) { ppRestoreMove!.ppUsed = Math.max(ppRestoreMove!.ppUsed - 10, 0); pokemon.scene.queueMessage(i18next.t("battle:ppHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), moveName: ppRestoreMove!.getName(), berryName: getBerryName(berryType) })); - } - }; + } + }; } } diff --git a/src/data/challenge.ts b/src/data/challenge.ts index e3ee818cee9..a64a90e5d14 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -185,7 +185,7 @@ export abstract class Challenge { */ getDescription(overrideValue?: number): string { const value = overrideValue ?? this.value; - return `${i18next.t([`challenges:${this.geti18nKey()}.desc.${value}`, `challenges:${this.geti18nKey()}.desc`])}`; + return `${i18next.t([ `challenges:${this.geti18nKey()}.desc.${value}`, `challenges:${this.geti18nKey()}.desc` ])}`; } /** @@ -414,9 +414,9 @@ export class SingleGenerationChallenge extends Challenge { } applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean { - const generations = [pokemon.generation]; + const generations = [ pokemon.generation ]; if (soft) { - const speciesToCheck = [pokemon.speciesId]; + const speciesToCheck = [ pokemon.speciesId ]; while (speciesToCheck.length) { const checking = speciesToCheck.pop(); if (checking && pokemonEvolutions.hasOwnProperty(checking)) { @@ -448,21 +448,21 @@ export class SingleGenerationChallenge extends Challenge { applyFixedBattle(waveIndex: Number, battleConfig: FixedBattleConfig): boolean { let trainerTypes: TrainerType[] = []; switch (waveIndex) { - case 182: - trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, Utils.randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]), TrainerType.MARNIE_ELITE, TrainerType.RIKA ]; - break; - case 184: - trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ]; - break; - case 186: - trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE]), TrainerType.LARRY_ELITE ]; - break; - case 188: - trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ]; - break; - case 190: - trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ]; - break; + case 182: + trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, Utils.randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]), TrainerType.MARNIE_ELITE, TrainerType.RIKA ]; + break; + case 184: + trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ]; + break; + case 186: + trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([ TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE ]), TrainerType.LARRY_ELITE ]; + break; + case 188: + trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ]; + break; + case 190: + trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ]; + break; } if (trainerTypes.length === 0) { return false; @@ -528,10 +528,10 @@ interface monotypeOverride { */ export class SingleTypeChallenge extends Challenge { private static TYPE_OVERRIDES: monotypeOverride[] = [ - {species: Species.CASTFORM, type: Type.NORMAL, fusion: false}, + { species: Species.CASTFORM, type: Type.NORMAL, fusion: false }, ]; // TODO: Find a solution for all Pokemon with this ssui issue, including Basculin and Burmy - private static SPECIES_OVERRIDES: Species[] = [Species.MELOETTA]; + private static SPECIES_OVERRIDES: Species[] = [ Species.MELOETTA ]; constructor() { super(Challenges.SINGLE_TYPE, 18); @@ -539,9 +539,9 @@ export class SingleTypeChallenge extends Challenge { override applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean { const speciesForm = getPokemonSpeciesForm(pokemon.speciesId, dexAttr.formIndex); - const types = [speciesForm.type1, speciesForm.type2]; + const types = [ speciesForm.type1, speciesForm.type2 ]; if (soft && !SingleTypeChallenge.SPECIES_OVERRIDES.includes(pokemon.speciesId)) { - const speciesToCheck = [pokemon.speciesId]; + const speciesToCheck = [ pokemon.speciesId ]; while (speciesToCheck.length) { const checking = speciesToCheck.pop(); if (checking && pokemonEvolutions.hasOwnProperty(checking)) { @@ -606,9 +606,9 @@ export class SingleTypeChallenge extends Challenge { overrideValue = this.value; } const type = i18next.t(`pokemonInfo:Type.${Type[this.value - 1]}`); - const typeColor = `[color=${TypeColor[Type[this.value-1]]}][shadow=${TypeShadow[Type[this.value-1]]}]${type}[/shadow][/color]`; + const typeColor = `[color=${TypeColor[Type[this.value - 1]]}][shadow=${TypeShadow[Type[this.value - 1]]}]${type}[/shadow][/color]`; const defaultDesc = i18next.t("challenges:singleType.desc_default"); - const typeDesc = i18next.t("challenges:singleType.desc", {type: typeColor}); + const typeDesc = i18next.t("challenges:singleType.desc", { type: typeColor }); return this.value === 0 ? defaultDesc : typeDesc; } @@ -653,7 +653,7 @@ export class FreshStartChallenge extends Challenge { pokemon.shiny = false; // Not shiny pokemon.variant = 0; // Not shiny pokemon.formIndex = 0; // Froakie should be base form - pokemon.ivs = [10, 10, 10, 10, 10, 10]; // Default IVs of 10 for all stats + pokemon.ivs = [ 10, 10, 10, 10, 10, 10 ]; // Default IVs of 10 for all stats return true; } @@ -891,45 +891,45 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType gameMode.challenges.forEach(c => { if (c.value !== 0) { switch (challengeType) { - case ChallengeType.STARTER_CHOICE: - ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3]); - break; - case ChallengeType.STARTER_POINTS: - ret ||= c.applyStarterPoints(args[0]); - break; - case ChallengeType.STARTER_COST: - ret ||= c.applyStarterCost(args[0], args[1]); - break; - case ChallengeType.STARTER_MODIFY: - ret ||= c.applyStarterModify(args[0]); - break; - case ChallengeType.POKEMON_IN_BATTLE: - ret ||= c.applyPokemonInBattle(args[0], args[1]); - break; - case ChallengeType.FIXED_BATTLES: - ret ||= c.applyFixedBattle(args[0], args[1]); - break; - case ChallengeType.TYPE_EFFECTIVENESS: - ret ||= c.applyTypeEffectiveness(args[0]); - break; - case ChallengeType.AI_LEVEL: - ret ||= c.applyLevelChange(args[0], args[1], args[2], args[3]); - break; - case ChallengeType.AI_MOVE_SLOTS: - ret ||= c.applyMoveSlot(args[0], args[1]); - break; - case ChallengeType.PASSIVE_ACCESS: - ret ||= c.applyPassiveAccess(args[0], args[1]); - break; - case ChallengeType.GAME_MODE_MODIFY: - ret ||= c.applyGameModeModify(gameMode); - break; - case ChallengeType.MOVE_ACCESS: - ret ||= c.applyMoveAccessLevel(args[0], args[1], args[2], args[3]); - break; - case ChallengeType.MOVE_WEIGHT: - ret ||= c.applyMoveWeight(args[0], args[1], args[2], args[3]); - break; + case ChallengeType.STARTER_CHOICE: + ret ||= c.applyStarterChoice(args[0], args[1], args[2], args[3]); + break; + case ChallengeType.STARTER_POINTS: + ret ||= c.applyStarterPoints(args[0]); + break; + case ChallengeType.STARTER_COST: + ret ||= c.applyStarterCost(args[0], args[1]); + break; + case ChallengeType.STARTER_MODIFY: + ret ||= c.applyStarterModify(args[0]); + break; + case ChallengeType.POKEMON_IN_BATTLE: + ret ||= c.applyPokemonInBattle(args[0], args[1]); + break; + case ChallengeType.FIXED_BATTLES: + ret ||= c.applyFixedBattle(args[0], args[1]); + break; + case ChallengeType.TYPE_EFFECTIVENESS: + ret ||= c.applyTypeEffectiveness(args[0]); + break; + case ChallengeType.AI_LEVEL: + ret ||= c.applyLevelChange(args[0], args[1], args[2], args[3]); + break; + case ChallengeType.AI_MOVE_SLOTS: + ret ||= c.applyMoveSlot(args[0], args[1]); + break; + case ChallengeType.PASSIVE_ACCESS: + ret ||= c.applyPassiveAccess(args[0], args[1]); + break; + case ChallengeType.GAME_MODE_MODIFY: + ret ||= c.applyGameModeModify(gameMode); + break; + case ChallengeType.MOVE_ACCESS: + ret ||= c.applyMoveAccessLevel(args[0], args[1], args[2], args[3]); + break; + case ChallengeType.MOVE_WEIGHT: + ret ||= c.applyMoveWeight(args[0], args[1], args[2], args[3]); + break; } } }); @@ -943,18 +943,18 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType */ export function copyChallenge(source: Challenge | any): Challenge { switch (source.id) { - case Challenges.SINGLE_GENERATION: - return SingleGenerationChallenge.loadChallenge(source); - case Challenges.SINGLE_TYPE: - return SingleTypeChallenge.loadChallenge(source); - case Challenges.LOWER_MAX_STARTER_COST: - return LowerStarterMaxCostChallenge.loadChallenge(source); - case Challenges.LOWER_STARTER_POINTS: - return LowerStarterPointsChallenge.loadChallenge(source); - case Challenges.FRESH_START: - return FreshStartChallenge.loadChallenge(source); - case Challenges.INVERSE_BATTLE: - return InverseBattleChallenge.loadChallenge(source); + case Challenges.SINGLE_GENERATION: + return SingleGenerationChallenge.loadChallenge(source); + case Challenges.SINGLE_TYPE: + return SingleTypeChallenge.loadChallenge(source); + case Challenges.LOWER_MAX_STARTER_COST: + return LowerStarterMaxCostChallenge.loadChallenge(source); + case Challenges.LOWER_STARTER_POINTS: + return LowerStarterPointsChallenge.loadChallenge(source); + case Challenges.FRESH_START: + return FreshStartChallenge.loadChallenge(source); + case Challenges.INVERSE_BATTLE: + return InverseBattleChallenge.loadChallenge(source); } throw new Error("Unknown challenge copied"); } diff --git a/src/data/dialogue.ts b/src/data/dialogue.ts index cf693a6315c..3219ce4d058 100644 --- a/src/data/dialogue.ts +++ b/src/data/dialogue.ts @@ -3123,44 +3123,44 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { export const doubleBattleDialogue = { "blue_red_double": { - encounter: ["doubleBattleDialogue:blue_red_double.encounter.1"], - victory: ["doubleBattleDialogue:blue_red_double.victory.1"] + encounter: [ "doubleBattleDialogue:blue_red_double.encounter.1" ], + victory: [ "doubleBattleDialogue:blue_red_double.victory.1" ] }, "red_blue_double": { - encounter: ["doubleBattleDialogue:red_blue_double.encounter.1"], - victory: ["doubleBattleDialogue:red_blue_double.victory.1"] + encounter: [ "doubleBattleDialogue:red_blue_double.encounter.1" ], + victory: [ "doubleBattleDialogue:red_blue_double.victory.1" ] }, "tate_liza_double": { - encounter: ["doubleBattleDialogue:tate_liza_double.encounter.1"], - victory: ["doubleBattleDialogue:tate_liza_double.victory.1"] + encounter: [ "doubleBattleDialogue:tate_liza_double.encounter.1" ], + victory: [ "doubleBattleDialogue:tate_liza_double.victory.1" ] }, "liza_tate_double": { - encounter: ["doubleBattleDialogue:liza_tate_double.encounter.1"], - victory: [ "doubleBattleDialogue:liza_tate_double.victory.1"] + encounter: [ "doubleBattleDialogue:liza_tate_double.encounter.1" ], + victory: [ "doubleBattleDialogue:liza_tate_double.victory.1" ] }, "wallace_steven_double": { - encounter: [ "doubleBattleDialogue:wallace_steven_double.encounter.1"], - victory: [ "doubleBattleDialogue:wallace_steven_double.victory.1"] + encounter: [ "doubleBattleDialogue:wallace_steven_double.encounter.1" ], + victory: [ "doubleBattleDialogue:wallace_steven_double.victory.1" ] }, "steven_wallace_double": { - encounter: [ "doubleBattleDialogue:steven_wallace_double.encounter.1"], - victory: [ "doubleBattleDialogue:steven_wallace_double.victory.1"] + encounter: [ "doubleBattleDialogue:steven_wallace_double.encounter.1" ], + victory: [ "doubleBattleDialogue:steven_wallace_double.victory.1" ] }, "alder_iris_double": { - encounter: [ "doubleBattleDialogue:alder_iris_double.encounter.1"], - victory: [ "doubleBattleDialogue:alder_iris_double.victory.1"] + encounter: [ "doubleBattleDialogue:alder_iris_double.encounter.1" ], + victory: [ "doubleBattleDialogue:alder_iris_double.victory.1" ] }, "iris_alder_double": { - encounter: [ "doubleBattleDialogue:iris_alder_double.encounter.1"], - victory: [ "doubleBattleDialogue:iris_alder_double.victory.1"] + encounter: [ "doubleBattleDialogue:iris_alder_double.encounter.1" ], + victory: [ "doubleBattleDialogue:iris_alder_double.victory.1" ] }, "marnie_piers_double": { - encounter: [ "doubleBattleDialogue:marnie_piers_double.encounter.1"], - victory: [ "doubleBattleDialogue:marnie_piers_double.victory.1"] + encounter: [ "doubleBattleDialogue:marnie_piers_double.encounter.1" ], + victory: [ "doubleBattleDialogue:marnie_piers_double.victory.1" ] }, "piers_marnie_double": { - encounter: [ "doubleBattleDialogue:piers_marnie_double.encounter.1"], - victory: [ "doubleBattleDialogue:piers_marnie_double.victory.1"] + encounter: [ "doubleBattleDialogue:piers_marnie_double.encounter.1" ], + victory: [ "doubleBattleDialogue:piers_marnie_double.victory.1" ] }, @@ -3193,7 +3193,7 @@ export function initTrainerTypeDialogue(): void { const trainerTypes = Object.keys(trainerTypeDialogue).map(t => parseInt(t) as TrainerType); for (const trainerType of trainerTypes) { const messages = trainerTypeDialogue[trainerType]; - const messageTypes = ["encounter", "victory", "defeat"]; + const messageTypes = [ "encounter", "victory", "defeat" ]; for (const messageType of messageTypes) { if (Array.isArray(messages)) { if (messages[0][messageType]) { diff --git a/src/data/egg-hatch-data.ts b/src/data/egg-hatch-data.ts index e754a9205c4..ba553b55c4f 100644 --- a/src/data/egg-hatch-data.ts +++ b/src/data/egg-hatch-data.ts @@ -48,7 +48,7 @@ export class EggHatchData { seenCount: currDexEntry.seenCount, caughtCount: currDexEntry.caughtCount, hatchedCount: currDexEntry.hatchedCount, - ivs: [...currDexEntry.ivs] + ivs: [ ...currDexEntry.ivs ] }; this.starterDataEntryBeforeUpdate = { moveset: currStarterDataEntry.moveset, diff --git a/src/data/egg.ts b/src/data/egg.ts index c83554f2a19..0f88c53b748 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -11,6 +11,7 @@ import { EggTier } from "#enums/egg-type"; import { Species } from "#enums/species"; import { EggSourceType } from "#enums/egg-source-types"; import { MANAPHY_EGG_MANAPHY_RATE, SAME_SPECIES_EGG_HA_RATE, GACHA_EGG_HA_RATE, GACHA_DEFAULT_RARE_EGGMOVE_RATE, SAME_SPECIES_EGG_RARE_EGGMOVE_RATE, GACHA_MOVE_UP_RARE_EGGMOVE_RATE, GACHA_DEFAULT_SHINY_RATE, GACHA_SHINY_UP_SHINY_RATE, SAME_SPECIES_EGG_SHINY_RATE, EGG_PITY_LEGENDARY_THRESHOLD, EGG_PITY_EPIC_THRESHOLD, EGG_PITY_RARE_THRESHOLD, SHINY_VARIANT_CHANCE, SHINY_EPIC_CHANCE, GACHA_DEFAULT_COMMON_EGG_THRESHOLD, GACHA_DEFAULT_RARE_EGG_THRESHOLD, GACHA_DEFAULT_EPIC_EGG_THRESHOLD, GACHA_LEGENDARY_UP_THRESHOLD_OFFSET, HATCH_WAVES_MANAPHY_EGG, HATCH_WAVES_COMMON_EGG, HATCH_WAVES_RARE_EGG, HATCH_WAVES_EPIC_EGG, HATCH_WAVES_LEGENDARY_EGG } from "#app/data/balance/rates"; +import { speciesEggTiers } from "#app/data/balance/species-egg-tiers"; export const EGG_SEED = 1073741824; @@ -160,7 +161,7 @@ export class Egg { // Override egg tier and hatchwaves if species was given if (eggOptions?.species) { - this._tier = this.getEggTierFromSpeciesStarterValue(); + this._tier = this.getEggTier(); this._hatchWaves = eggOptions.hatchWaves ?? this.getEggTierDefaultHatchWaves(); } // If species has no variant, set variantTier to common. This needs to @@ -261,14 +262,14 @@ export class Egg { return "Manaphy"; } switch (this.tier) { - case EggTier.GREAT: - return i18next.t("egg:greatTier"); - case EggTier.ULTRA: - return i18next.t("egg:ultraTier"); - case EggTier.MASTER: - return i18next.t("egg:masterTier"); - default: - return i18next.t("egg:defaultTier"); + case EggTier.RARE: + return i18next.t("egg:greatTier"); + case EggTier.EPIC: + return i18next.t("egg:ultraTier"); + case EggTier.LEGENDARY: + return i18next.t("egg:masterTier"); + default: + return i18next.t("egg:defaultTier"); } } @@ -287,19 +288,19 @@ export class Egg { public getEggTypeDescriptor(scene: BattleScene): string { switch (this.sourceType) { - case EggSourceType.SAME_SPECIES_EGG: - return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName()}); - case EggSourceType.GACHA_LEGENDARY: - return this._eggDescriptor ?? `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`; - case EggSourceType.GACHA_SHINY: - return this._eggDescriptor ?? i18next.t("egg:gachaTypeShiny"); - case EggSourceType.GACHA_MOVE: - return this._eggDescriptor ?? i18next.t("egg:gachaTypeMove"); - case EggSourceType.EVENT: - return this._eggDescriptor ?? i18next.t("egg:eventType"); - default: - console.warn("getEggTypeDescriptor case not defined. Returning default empty string"); - return ""; + case EggSourceType.SAME_SPECIES_EGG: + return this._eggDescriptor ?? i18next.t("egg:sameSpeciesEgg", { species: getPokemonSpecies(this._species).getName() }); + case EggSourceType.GACHA_LEGENDARY: + return this._eggDescriptor ?? `${i18next.t("egg:gachaTypeLegendary")} (${getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp)).getName()})`; + case EggSourceType.GACHA_SHINY: + return this._eggDescriptor ?? i18next.t("egg:gachaTypeShiny"); + case EggSourceType.GACHA_MOVE: + return this._eggDescriptor ?? i18next.t("egg:gachaTypeMove"); + case EggSourceType.EVENT: + return this._eggDescriptor ?? i18next.t("egg:eventType"); + default: + console.warn("getEggTypeDescriptor case not defined. Returning default empty string"); + return ""; } } @@ -314,14 +315,14 @@ export class Egg { private rollEggMoveIndex() { let baseChance = GACHA_DEFAULT_RARE_EGGMOVE_RATE; switch (this._sourceType) { - case EggSourceType.SAME_SPECIES_EGG: - baseChance = SAME_SPECIES_EGG_RARE_EGGMOVE_RATE; - break; - case EggSourceType.GACHA_MOVE: - baseChance = GACHA_MOVE_UP_RARE_EGGMOVE_RATE; - break; - default: - break; + case EggSourceType.SAME_SPECIES_EGG: + baseChance = SAME_SPECIES_EGG_RARE_EGGMOVE_RATE; + break; + case EggSourceType.GACHA_MOVE: + baseChance = GACHA_MOVE_UP_RARE_EGGMOVE_RATE; + break; + default: + break; } const tierMultiplier = this.isManaphyEgg() ? 2 : Math.pow(2, 3 - this.tier); @@ -334,12 +335,12 @@ export class Egg { } switch (eggTier ?? this._tier) { - case EggTier.COMMON: - return HATCH_WAVES_COMMON_EGG; - case EggTier.GREAT: - return HATCH_WAVES_RARE_EGG; - case EggTier.ULTRA: - return HATCH_WAVES_EPIC_EGG; + case EggTier.COMMON: + return HATCH_WAVES_COMMON_EGG; + case EggTier.RARE: + return HATCH_WAVES_RARE_EGG; + case EggTier.EPIC: + return HATCH_WAVES_EPIC_EGG; } return HATCH_WAVES_LEGENDARY_EGG; } @@ -347,7 +348,7 @@ export class Egg { private rollEggTier(): EggTier { const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? GACHA_LEGENDARY_UP_THRESHOLD_OFFSET : 0; const tierValue = Utils.randInt(256); - return tierValue >= GACHA_DEFAULT_COMMON_EGG_THRESHOLD + tierValueOffset ? EggTier.COMMON : tierValue >= GACHA_DEFAULT_RARE_EGG_THRESHOLD + tierValueOffset ? EggTier.GREAT : tierValue >= GACHA_DEFAULT_EPIC_EGG_THRESHOLD + tierValueOffset ? EggTier.ULTRA : EggTier.MASTER; + return tierValue >= GACHA_DEFAULT_COMMON_EGG_THRESHOLD + tierValueOffset ? EggTier.COMMON : tierValue >= GACHA_DEFAULT_RARE_EGG_THRESHOLD + tierValueOffset ? EggTier.RARE : tierValue >= GACHA_DEFAULT_EPIC_EGG_THRESHOLD + tierValueOffset ? EggTier.EPIC : EggTier.LEGENDARY; } private rollSpecies(scene: BattleScene): Species | null { @@ -367,7 +368,7 @@ export class Egg { */ const rand = (Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) !== 1); return rand ? Species.PHIONE : Species.MANAPHY; - } else if (this.tier === EggTier.MASTER + } else if (this.tier === EggTier.LEGENDARY && this._sourceType === EggSourceType.GACHA_LEGENDARY) { if (!Utils.randSeedInt(2)) { return getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp); @@ -378,28 +379,28 @@ export class Egg { let maxStarterValue: integer; switch (this.tier) { - case EggTier.GREAT: - minStarterValue = 4; - maxStarterValue = 5; - break; - case EggTier.ULTRA: - minStarterValue = 6; - maxStarterValue = 7; - break; - case EggTier.MASTER: - minStarterValue = 8; - maxStarterValue = 9; - break; - default: - minStarterValue = 1; - maxStarterValue = 3; - break; + case EggTier.RARE: + minStarterValue = 4; + maxStarterValue = 5; + break; + case EggTier.EPIC: + minStarterValue = 6; + maxStarterValue = 7; + break; + case EggTier.LEGENDARY: + minStarterValue = 8; + maxStarterValue = 9; + break; + default: + minStarterValue = 1; + maxStarterValue = 3; + break; } - const ignoredSpecies = [Species.PHIONE, Species.MANAPHY, Species.ETERNATUS]; + const ignoredSpecies = [ Species.PHIONE, Species.MANAPHY, Species.ETERNATUS ]; - let speciesPool = Object.keys(speciesStarterCosts) - .filter(s => speciesStarterCosts[s] >= minStarterValue && speciesStarterCosts[s] <= maxStarterValue) + let speciesPool = Object.keys(speciesEggTiers) + .filter(s => speciesEggTiers[s] === this.tier) .map(s => parseInt(s) as Species) .filter(s => !pokemonPrevolutions.hasOwnProperty(s) && getPokemonSpecies(s).isObtainable() && ignoredSpecies.indexOf(s) === -1); @@ -430,7 +431,9 @@ export class Egg { let totalWeight = 0; const speciesWeights : number[] = []; for (const speciesId of speciesPool) { - let weight = Math.floor((((maxStarterValue - speciesStarterCosts[speciesId]) / ((maxStarterValue - minStarterValue) + 1)) * 1.5 + 1) * 100); + // Accounts for species that have starter costs outside of the normal range for their EggTier + const speciesCostClamped = Phaser.Math.Clamp(speciesStarterCosts[speciesId], minStarterValue, maxStarterValue); + let weight = Math.floor((((maxStarterValue - speciesCostClamped) / ((maxStarterValue - minStarterValue) + 1)) * 1.5 + 1) * 100); const species = getPokemonSpecies(speciesId); if (species.isRegional()) { weight = Math.floor(weight / 2); @@ -466,14 +469,14 @@ export class Egg { private rollShiny(): boolean { let shinyChance = GACHA_DEFAULT_SHINY_RATE; switch (this._sourceType) { - case EggSourceType.GACHA_SHINY: - shinyChance = GACHA_SHINY_UP_SHINY_RATE; - break; - case EggSourceType.SAME_SPECIES_EGG: - shinyChance = SAME_SPECIES_EGG_SHINY_RATE; - break; - default: - break; + case EggSourceType.GACHA_SHINY: + shinyChance = GACHA_SHINY_UP_SHINY_RATE; + break; + case EggSourceType.SAME_SPECIES_EGG: + shinyChance = SAME_SPECIES_EGG_SHINY_RATE; + break; + default: + break; } return !Utils.randSeedInt(shinyChance); @@ -498,16 +501,16 @@ export class Egg { private checkForPityTierOverrides(scene: BattleScene): void { const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? GACHA_LEGENDARY_UP_THRESHOLD_OFFSET : 0; - scene.gameData.eggPity[EggTier.GREAT] += 1; - scene.gameData.eggPity[EggTier.ULTRA] += 1; - scene.gameData.eggPity[EggTier.MASTER] += 1 + tierValueOffset; + scene.gameData.eggPity[EggTier.RARE] += 1; + scene.gameData.eggPity[EggTier.EPIC] += 1; + scene.gameData.eggPity[EggTier.LEGENDARY] += 1 + tierValueOffset; // These numbers are roughly the 80% mark. That is, 80% of the time you'll get an egg before this gets triggered. - if (scene.gameData.eggPity[EggTier.MASTER] >= EGG_PITY_LEGENDARY_THRESHOLD && this._tier === EggTier.COMMON) { - this._tier = EggTier.MASTER; - } else if (scene.gameData.eggPity[EggTier.ULTRA] >= EGG_PITY_EPIC_THRESHOLD && this._tier === EggTier.COMMON) { - this._tier = EggTier.ULTRA; - } else if (scene.gameData.eggPity[EggTier.GREAT] >= EGG_PITY_RARE_THRESHOLD && this._tier === EggTier.COMMON) { - this._tier = EggTier.GREAT; + if (scene.gameData.eggPity[EggTier.LEGENDARY] >= EGG_PITY_LEGENDARY_THRESHOLD && this._tier === EggTier.COMMON) { + this._tier = EggTier.LEGENDARY; + } else if (scene.gameData.eggPity[EggTier.EPIC] >= EGG_PITY_EPIC_THRESHOLD && this._tier === EggTier.COMMON) { + this._tier = EggTier.EPIC; + } else if (scene.gameData.eggPity[EggTier.RARE] >= EGG_PITY_RARE_THRESHOLD && this._tier === EggTier.COMMON) { + this._tier = EggTier.RARE; } scene.gameData.eggPity[this._tier] = 0; } @@ -516,38 +519,24 @@ export class Egg { scene.gameData.gameStats.eggsPulled++; if (this.isManaphyEgg()) { scene.gameData.gameStats.manaphyEggsPulled++; - this._hatchWaves = this.getEggTierDefaultHatchWaves(EggTier.ULTRA); + this._hatchWaves = this.getEggTierDefaultHatchWaves(EggTier.EPIC); return; } switch (this.tier) { - case EggTier.GREAT: - scene.gameData.gameStats.rareEggsPulled++; - break; - case EggTier.ULTRA: - scene.gameData.gameStats.epicEggsPulled++; - break; - case EggTier.MASTER: - scene.gameData.gameStats.legendaryEggsPulled++; - break; + case EggTier.RARE: + scene.gameData.gameStats.rareEggsPulled++; + break; + case EggTier.EPIC: + scene.gameData.gameStats.epicEggsPulled++; + break; + case EggTier.LEGENDARY: + scene.gameData.gameStats.legendaryEggsPulled++; + break; } } - private getEggTierFromSpeciesStarterValue(): EggTier { - const speciesStartValue = speciesStarterCosts[this.species]; - if (speciesStartValue >= 1 && speciesStartValue <= 3) { - return EggTier.COMMON; - } - if (speciesStartValue >= 4 && speciesStartValue <= 5) { - return EggTier.GREAT; - } - if (speciesStartValue >= 6 && speciesStartValue <= 7) { - return EggTier.ULTRA; - } - if (speciesStartValue >= 8) { - return EggTier.MASTER; - } - - return EggTier.COMMON; + private getEggTier(): EggTier { + return speciesEggTiers[this.species]; } //// @@ -556,8 +545,8 @@ export class Egg { } export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timestamp: number): Species { - const legendarySpecies = Object.entries(speciesStarterCosts) - .filter(s => s[1] >= 8 && s[1] <= 9) + const legendarySpecies = Object.entries(speciesEggTiers) + .filter(s => s[1] === EggTier.LEGENDARY) .map(s => parseInt(s[0])) .filter(s => getPokemonSpecies(s).isObtainable()); @@ -579,17 +568,9 @@ export function getLegendaryGachaSpeciesForTimestamp(scene: BattleScene, timesta /** * Check for a given species EggTier Value - * @param species - Species for wich we will check the egg tier it belongs to + * @param pokemonSpecies - Species for wich we will check the egg tier it belongs to * @returns The egg tier of a given pokemon species */ export function getEggTierForSpecies(pokemonSpecies :PokemonSpecies): EggTier { - const speciesBaseValue = speciesStarterCosts[pokemonSpecies.getRootSpeciesId()]; - if (speciesBaseValue <= 3) { - return EggTier.COMMON; - } else if (speciesBaseValue <= 5) { - return EggTier.GREAT; - } else if (speciesBaseValue <= 7) { - return EggTier.ULTRA; - } - return EggTier.MASTER; + return speciesEggTiers[pokemonSpecies.getRootSpeciesId()]; } diff --git a/src/data/exp.ts b/src/data/exp.ts index 3b332eb7cf2..c03abddadfc 100644 --- a/src/data/exp.ts +++ b/src/data/exp.ts @@ -28,24 +28,24 @@ export function getLevelTotalExp(level: integer, growthRate: GrowthRate): intege let ret: integer; switch (growthRate) { - case GrowthRate.ERRATIC: - ret = (Math.pow(level, 4) + (Math.pow(level, 3) * 2000)) / 3500; - break; - case GrowthRate.FAST: - ret = Math.pow(level, 3) * 4 / 5; - break; - case GrowthRate.MEDIUM_FAST: - ret = Math.pow(level, 3); - break; - case GrowthRate.MEDIUM_SLOW: - ret = (Math.pow(level, 3) * 6 / 5) - (15 * Math.pow(level, 2)) + (100 * level) - 140; - break; - case GrowthRate.SLOW: - ret = Math.pow(level, 3) * 5 / 4; - break; - case GrowthRate.FLUCTUATING: - ret = (Math.pow(level, 3) * ((level / 2) + 8)) * 4 / (100 + level); - break; + case GrowthRate.ERRATIC: + ret = (Math.pow(level, 4) + (Math.pow(level, 3) * 2000)) / 3500; + break; + case GrowthRate.FAST: + ret = Math.pow(level, 3) * 4 / 5; + break; + case GrowthRate.MEDIUM_FAST: + ret = Math.pow(level, 3); + break; + case GrowthRate.MEDIUM_SLOW: + ret = (Math.pow(level, 3) * 6 / 5) - (15 * Math.pow(level, 2)) + (100 * level) - 140; + break; + case GrowthRate.SLOW: + ret = Math.pow(level, 3) * 5 / 4; + break; + case GrowthRate.FLUCTUATING: + ret = (Math.pow(level, 3) * ((level / 2) + 8)) * 4 / (100 + level); + break; } if (growthRate !== GrowthRate.MEDIUM_FAST) { @@ -61,17 +61,17 @@ export function getLevelRelExp(level: integer, growthRate: GrowthRate): number { export function getGrowthRateColor(growthRate: GrowthRate, shadow?: boolean) { switch (growthRate) { - case GrowthRate.ERRATIC: - return !shadow ? "#f85888" : "#906060"; - case GrowthRate.FAST: - return !shadow ? "#f8d030" : "#b8a038"; - case GrowthRate.MEDIUM_FAST: - return !shadow ? "#78c850" : "#588040"; - case GrowthRate.MEDIUM_SLOW: - return !shadow ? "#6890f0" : "#807870"; - case GrowthRate.SLOW: - return !shadow ? "#f08030" : "#c03028"; - case GrowthRate.FLUCTUATING: - return !shadow ? "#a040a0" : "#483850"; + case GrowthRate.ERRATIC: + return !shadow ? "#f85888" : "#906060"; + case GrowthRate.FAST: + return !shadow ? "#f8d030" : "#b8a038"; + case GrowthRate.MEDIUM_FAST: + return !shadow ? "#78c850" : "#588040"; + case GrowthRate.MEDIUM_SLOW: + return !shadow ? "#6890f0" : "#807870"; + case GrowthRate.SLOW: + return !shadow ? "#f08030" : "#c03028"; + case GrowthRate.FLUCTUATING: + return !shadow ? "#a040a0" : "#483850"; } } diff --git a/src/data/gender.ts b/src/data/gender.ts index 0d4b76d8bd1..dae7723dd85 100644 --- a/src/data/gender.ts +++ b/src/data/gender.ts @@ -6,20 +6,20 @@ export enum Gender { export function getGenderSymbol(gender: Gender) { switch (gender) { - case Gender.MALE: - return "♂"; - case Gender.FEMALE: - return "♀"; + case Gender.MALE: + return "♂"; + case Gender.FEMALE: + return "♀"; } return ""; } export function getGenderColor(gender: Gender, shadow?: boolean) { switch (gender) { - case Gender.MALE: - return shadow ? "#006090" : "#40c8f8"; - case Gender.FEMALE: - return shadow ? "#984038" : "#f89890"; + case Gender.MALE: + return shadow ? "#006090" : "#40c8f8"; + case Gender.FEMALE: + return shadow ? "#984038" : "#f89890"; } return "#ffffff"; } diff --git a/src/data/move.ts b/src/data/move.ts index 8c9e8b0fb99..309a2d3a7eb 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -274,16 +274,16 @@ export default class Move implements Localizable { */ isMultiTarget(): boolean { switch (this.moveTarget) { - case MoveTarget.ALL_OTHERS: - case MoveTarget.ALL_NEAR_OTHERS: - case MoveTarget.ALL_NEAR_ENEMIES: - case MoveTarget.ALL_ENEMIES: - case MoveTarget.USER_AND_ALLIES: - case MoveTarget.ALL: - case MoveTarget.USER_SIDE: - case MoveTarget.ENEMY_SIDE: - case MoveTarget.BOTH_SIDES: - return true; + case MoveTarget.ALL_OTHERS: + case MoveTarget.ALL_NEAR_OTHERS: + case MoveTarget.ALL_NEAR_ENEMIES: + case MoveTarget.ALL_ENEMIES: + case MoveTarget.USER_AND_ALLIES: + case MoveTarget.ALL: + case MoveTarget.USER_SIDE: + case MoveTarget.ENEMY_SIDE: + case MoveTarget.BOTH_SIDES: + return true; } return false; } @@ -295,13 +295,13 @@ export default class Move implements Localizable { isAllyTarget(): boolean { switch (this.moveTarget) { - case MoveTarget.USER: - case MoveTarget.NEAR_ALLY: - case MoveTarget.ALLY: - case MoveTarget.USER_OR_NEAR_ALLY: - case MoveTarget.USER_AND_ALLIES: - case MoveTarget.USER_SIDE: - return true; + case MoveTarget.USER: + case MoveTarget.NEAR_ALLY: + case MoveTarget.ALLY: + case MoveTarget.USER_OR_NEAR_ALLY: + case MoveTarget.USER_AND_ALLIES: + case MoveTarget.USER_SIDE: + return true; } return false; } @@ -320,16 +320,16 @@ export default class Move implements Localizable { } switch (type) { - case Type.GRASS: - if (this.hasFlag(MoveFlags.POWDER_MOVE)) { - return true; - } - break; - case Type.DARK: - if (user.hasAbility(Abilities.PRANKSTER) && this.category === MoveCategory.STATUS && (user.isPlayer() !== target.isPlayer())) { - return true; - } - break; + case Type.GRASS: + if (this.hasFlag(MoveFlags.POWDER_MOVE)) { + return true; + } + break; + case Type.DARK: + if (user.hasAbility(Abilities.PRANKSTER) && this.category === MoveCategory.STATUS && (user.isPlayer() !== target.isPlayer())) { + return true; + } + break; } return false; } @@ -341,7 +341,7 @@ export default class Move implements Localizable { * @returns `true` if the move can bypass the target's Substitute; `false` otherwise. */ hitsSubstitute(user: Pokemon, target: Pokemon | null): boolean { - if ([MoveTarget.USER, MoveTarget.USER_SIDE, MoveTarget.ENEMY_SIDE, MoveTarget.BOTH_SIDES].includes(this.moveTarget) + if ([ MoveTarget.USER, MoveTarget.USER_SIDE, MoveTarget.ENEMY_SIDE, MoveTarget.BOTH_SIDES ].includes(this.moveTarget) || !target?.getTag(BattlerTagType.SUBSTITUTE)) { return false; } @@ -365,6 +365,14 @@ export default class Move implements Localizable { return this; } + /** + * Internal dev flag for documenting edge cases. When using this, please document the known edge case. + * @returns the called object {@linkcode Move} + */ + edgeCase(): this { + return this; + } + /** * Marks the move as "partial": appends texts to the move name * @returns the called object {@linkcode Move} @@ -608,26 +616,26 @@ export default class Move implements Localizable { checkFlag(flag: MoveFlags, user: Pokemon, target: Pokemon | null): boolean { // special cases below, eg: if the move flag is MAKES_CONTACT, and the user pokemon has an ability that ignores contact (like "Long Reach"), then overrides and move does not make contact switch (flag) { - case MoveFlags.MAKES_CONTACT: - if (user.hasAbilityWithAttr(IgnoreContactAbAttr) || this.hitsSubstitute(user, target)) { - return false; - } - break; - case MoveFlags.IGNORE_ABILITIES: - if (user.hasAbilityWithAttr(MoveAbilityBypassAbAttr)) { - const abilityEffectsIgnored = new Utils.BooleanHolder(false); - applyAbAttrs(MoveAbilityBypassAbAttr, user, abilityEffectsIgnored, false, this); - if (abilityEffectsIgnored.value) { + case MoveFlags.MAKES_CONTACT: + if (user.hasAbilityWithAttr(IgnoreContactAbAttr) || this.hitsSubstitute(user, target)) { + return false; + } + break; + case MoveFlags.IGNORE_ABILITIES: + if (user.hasAbilityWithAttr(MoveAbilityBypassAbAttr)) { + const abilityEffectsIgnored = new Utils.BooleanHolder(false); + applyAbAttrs(MoveAbilityBypassAbAttr, user, abilityEffectsIgnored, false, this); + if (abilityEffectsIgnored.value) { + return true; + } + } + break; + case MoveFlags.IGNORE_PROTECT: + if (user.hasAbilityWithAttr(IgnoreProtectOnContactAbAttr) + && this.checkFlag(MoveFlags.MAKES_CONTACT, user, null)) { return true; } - } - break; - case MoveFlags.IGNORE_PROTECT: - if (user.hasAbilityWithAttr(IgnoreProtectOnContactAbAttr) - && this.checkFlag(MoveFlags.MAKES_CONTACT, user, null)) { - return true; - } - break; + break; } return !!(this.flags & flag); @@ -782,7 +790,7 @@ export default class Move implements Localizable { .flat(), ); for (const aura of fieldAuras) { - aura.applyPreAttack(source, null, simulated, target, this, [power]); + aura.applyPreAttack(source, null, simulated, target, this, [ power ]); } const alliedField: Pokemon[] = source instanceof PlayerPokemon ? source.scene.getPlayerField() : source.scene.getEnemyField(); @@ -800,7 +808,7 @@ export default class Move implements Localizable { source.scene.applyModifiers(PokemonMultiHitModifier, source.isPlayer(), source, new Utils.IntegerHolder(0), power); if (!this.hasAttr(TypelessAttr)) { - source.scene.arena.applyTags(WeakenMoveTypeTag, this.type, power); + source.scene.arena.applyTags(WeakenMoveTypeTag, simulated, this.type, power); source.scene.applyModifiers(AttackTypeBoosterModifier, source.isPlayer(), source, this.type, power); } @@ -970,13 +978,16 @@ export class MoveEffectAttr extends MoveAttr { public lastHitOnly: boolean; /** Should this effect only apply on the first target hit? */ public firstTargetOnly: boolean; + /** Overrides the secondary effect chance for this attr if set. */ + public effectChanceOverride?: number; - constructor(selfTarget?: boolean, trigger?: MoveEffectTrigger, firstHitOnly: boolean = false, lastHitOnly: boolean = false, firstTargetOnly: boolean = false) { + constructor(selfTarget?: boolean, trigger?: MoveEffectTrigger, firstHitOnly: boolean = false, lastHitOnly: boolean = false, firstTargetOnly: boolean = false, effectChanceOverride?: number) { super(selfTarget); - this.trigger = trigger !== undefined ? trigger : MoveEffectTrigger.POST_APPLY; + this.trigger = trigger ?? MoveEffectTrigger.POST_APPLY; this.firstHitOnly = firstHitOnly; this.lastHitOnly = lastHitOnly; this.firstTargetOnly = firstTargetOnly; + this.effectChanceOverride = effectChanceOverride; } /** @@ -1001,16 +1012,23 @@ export class MoveEffectAttr extends MoveAttr { /** * Gets the used move's additional effect chance. - * If user's ability has MoveEffectChanceMultiplierAbAttr or IgnoreMoveEffectsAbAttr modifies the base chance. + * Chance is modified by {@linkcode MoveEffectChanceMultiplierAbAttr} and {@linkcode IgnoreMoveEffectsAbAttr}. * @param user {@linkcode Pokemon} using this move - * @param target {@linkcode Pokemon} target of this move + * @param target {@linkcode Pokemon | Target} of this move * @param move {@linkcode Move} being used - * @param selfEffect {@linkcode Boolean} if move targets user. - * @returns Move chance value. + * @param selfEffect `true` if move targets user. + * @returns Move effect chance value. */ getMoveChance(user: Pokemon, target: Pokemon, move: Move, selfEffect?: Boolean, showAbility?: Boolean): integer { - const moveChance = new Utils.NumberHolder(move.chance); + const moveChance = new Utils.NumberHolder(this.effectChanceOverride ?? move.chance); + applyAbAttrs(MoveEffectChanceMultiplierAbAttr, user, null, false, moveChance, move, target, selfEffect, showAbility); + + if ((!move.hasAttr(FlinchAttr) || moveChance.value <= move.chance) && !move.hasAttr(SecretPowerAttr)) { + const userSide = user.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; + user.scene.arena.applyTagsForSide(ArenaTagType.WATER_FIRE_PLEDGE, userSide, false, moveChance); + } + if (!selfEffect) { applyPreDefendAbAttrs(IgnoreMoveEffectsAbAttr, target, user, null, null, false, moveChance); } @@ -1328,7 +1346,7 @@ export class RecoilAttr extends MoveEffectAttr { } user.damageAndUpdate(recoilDamage, HitResult.OTHER, false, true, true); - user.scene.queueMessage(i18next.t("moveTriggers:hitWithRecoil", {pokemonName: getPokemonNameWithAffix(user)})); + user.scene.queueMessage(i18next.t("moveTriggers:hitWithRecoil", { pokemonName: getPokemonNameWithAffix(user) })); user.turnData.damageTaken += recoilDamage; return true; @@ -1439,8 +1457,8 @@ export class HalfSacrificialAttr extends MoveEffectAttr { // Check to see if the Pokemon has an ability that blocks non-direct damage applyAbAttrs(BlockNonDirectDamageAbAttr, user, cancelled); if (!cancelled.value) { - user.damageAndUpdate(Utils.toDmgValue(user.getMaxHp()/2), HitResult.OTHER, false, true, true); - user.scene.queueMessage(i18next.t("moveTriggers:cutHpPowerUpMove", {pokemonName: getPokemonNameWithAffix(user)})); // Queue recoil message + user.damageAndUpdate(Utils.toDmgValue(user.getMaxHp() / 2), HitResult.OTHER, false, true, true); + user.scene.queueMessage(i18next.t("moveTriggers:cutHpPowerUpMove", { pokemonName: getPokemonNameWithAffix(user) })); // Queue recoil message } return true; } @@ -1449,7 +1467,7 @@ export class HalfSacrificialAttr extends MoveEffectAttr { if (user.isBoss()) { return -10; } - return Math.ceil(((1 - user.getHpRatio()/2) * 10 - 10) * (target.getAttackTypeEffectiveness(move.type, user) - 0.5)); + return Math.ceil(((1 - user.getHpRatio() / 2) * 10 - 10) * (target.getAttackTypeEffectiveness(move.type, user) - 0.5)); } } @@ -1546,7 +1564,7 @@ export class HealAttr extends MoveEffectAttr { */ addHealPhase(target: Pokemon, healRatio: number) { target.scene.unshiftPhase(new PokemonHealPhase(target.scene, target.getBattlerIndex(), - Utils.toDmgValue(target.getMaxHp() * healRatio), i18next.t("moveTriggers:healHp", {pokemonName: getPokemonNameWithAffix(target)}), true, !this.showAnim)); + Utils.toDmgValue(target.getMaxHp() * healRatio), i18next.t("moveTriggers:healHp", { pokemonName: getPokemonNameWithAffix(target) }), true, !this.showAnim)); } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { @@ -1637,7 +1655,7 @@ export class FlameBurstAttr extends MoveEffectAttr { return false; } - targetAlly.damageAndUpdate(Math.max(1, Math.floor(1/16 * targetAlly.getMaxHp())), HitResult.OTHER); + targetAlly.damageAndUpdate(Math.max(1, Math.floor(1 / 16 * targetAlly.getMaxHp())), HitResult.OTHER); return true; } @@ -1660,7 +1678,7 @@ export class SacrificialFullRestoreAttr extends SacrificialAttr { const maxPartyMemberHp = user.scene.getParty().map(p => p.getMaxHp()).reduce((maxHp: integer, hp: integer) => Math.max(hp, maxHp), 0); user.scene.pushPhase(new PokemonHealPhase(user.scene, user.getBattlerIndex(), - maxPartyMemberHp, i18next.t("moveTriggers:sacrificialFullRestore", {pokemonName: getPokemonNameWithAffix(user)}), true, false, false, true), true); + maxPartyMemberHp, i18next.t("moveTriggers:sacrificialFullRestore", { pokemonName: getPokemonNameWithAffix(user) }), true, false, false, true), true); return true; } @@ -1697,7 +1715,7 @@ export class IgnoreWeatherTypeDebuffAttr extends MoveAttr { * @returns true if the function succeeds */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - const weatherModifier=args[0] as Utils.NumberHolder; + const weatherModifier = args[0] as Utils.NumberHolder; //If the type-based attack power modifier due to weather (e.g. Water moves in Sun) is below 1, set it to 1 if (user.scene.arena.weather?.weatherType === this.weather) { weatherModifier.value = Math.max(weatherModifier.value, 1); @@ -1727,17 +1745,17 @@ export abstract class WeatherHealAttr extends HealAttr { export class PlantHealAttr extends WeatherHealAttr { getWeatherHealRatio(weatherType: WeatherType): number { switch (weatherType) { - case WeatherType.SUNNY: - case WeatherType.HARSH_SUN: - return 2 / 3; - case WeatherType.RAIN: - case WeatherType.SANDSTORM: - case WeatherType.HAIL: - case WeatherType.SNOW: - case WeatherType.HEAVY_RAIN: - return 0.25; - default: - return 0.5; + case WeatherType.SUNNY: + case WeatherType.HARSH_SUN: + return 2 / 3; + case WeatherType.RAIN: + case WeatherType.SANDSTORM: + case WeatherType.HAIL: + case WeatherType.SNOW: + case WeatherType.HEAVY_RAIN: + return 0.25; + default: + return 0.5; } } } @@ -1745,10 +1763,10 @@ export class PlantHealAttr extends WeatherHealAttr { export class SandHealAttr extends WeatherHealAttr { getWeatherHealRatio(weatherType: WeatherType): number { switch (weatherType) { - case WeatherType.SANDSTORM: - return 2 / 3; - default: - return 0.5; + case WeatherType.SANDSTORM: + return 2 / 3; + default: + return 0.5; } } } @@ -1845,11 +1863,11 @@ export class HitHealAttr extends MoveEffectAttr { if (this.healStat !== null) { // Strength Sap formula healAmount = target.getEffectiveStat(this.healStat); - message = i18next.t("battle:drainMessage", {pokemonName: getPokemonNameWithAffix(target)}); + message = i18next.t("battle:drainMessage", { pokemonName: getPokemonNameWithAffix(target) }); } else { // Default healing formula used by draining moves like Absorb, Draining Kiss, Bitter Blade, etc. healAmount = Utils.toDmgValue(user.turnData.currDamageDealt * this.healRatio); - message = i18next.t("battle:regainHealth", {pokemonName: getPokemonNameWithAffix(user)}); + message = i18next.t("battle:regainHealth", { pokemonName: getPokemonNameWithAffix(user) }); } if (reverseDrain) { if (user.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { @@ -1875,7 +1893,7 @@ export class HitHealAttr extends MoveEffectAttr { getUserBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer { if (this.healStat) { const healAmount = target.getEffectiveStat(this.healStat); - return Math.floor(Math.max(0, (Math.min(1, (healAmount+user.hp)/user.getMaxHp() - 0.33))) / user.getHpRatio()); + return Math.floor(Math.max(0, (Math.min(1, (healAmount + user.hp) / user.getMaxHp() - 0.33))) / user.getHpRatio()); } return Math.floor(Math.max((1 - user.getHpRatio()) - 0.33, 0) * (move.power / 4)); } @@ -1928,12 +1946,21 @@ export class IncrementMovePriorityAttr extends MoveAttr { * @see {@linkcode apply} */ export class MultiHitAttr extends MoveAttr { + /** This move's intrinsic multi-hit type. It should never be modified. */ + private readonly intrinsicMultiHitType: MultiHitType; + /** This move's current multi-hit type. It may be temporarily modified by abilities (e.g., Battle Bond). */ private multiHitType: MultiHitType; constructor(multiHitType?: MultiHitType) { super(); - this.multiHitType = multiHitType !== undefined ? multiHitType : MultiHitType._2_TO_5; + this.intrinsicMultiHitType = multiHitType !== undefined ? multiHitType : MultiHitType._2_TO_5; + this.multiHitType = this.intrinsicMultiHitType; + } + + // Currently used by `battle_bond.test.ts` + getMultiHitType(): MultiHitType { + return this.multiHitType; } /** @@ -1947,7 +1974,7 @@ export class MultiHitAttr extends MoveAttr { * @returns True */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - const hitType = new Utils.NumberHolder(this.multiHitType); + const hitType = new Utils.NumberHolder(this.intrinsicMultiHitType); applyMoveAttrs(ChangeMultiHitTypeAttr, user, target, move, hitType); this.multiHitType = hitType.value; @@ -1969,33 +1996,33 @@ export class MultiHitAttr extends MoveAttr { */ getHitCount(user: Pokemon, target: Pokemon): integer { switch (this.multiHitType) { - case MultiHitType._2_TO_5: - { - const rand = user.randSeedInt(16); - const hitValue = new Utils.IntegerHolder(rand); - applyAbAttrs(MaxMultiHitAbAttr, user, null, false, hitValue); - if (hitValue.value >= 10) { - return 2; - } else if (hitValue.value >= 4) { - return 3; - } else if (hitValue.value >= 2) { - return 4; - } else { - return 5; + case MultiHitType._2_TO_5: + { + const rand = user.randSeedInt(16); + const hitValue = new Utils.IntegerHolder(rand); + applyAbAttrs(MaxMultiHitAbAttr, user, null, false, hitValue); + if (hitValue.value >= 10) { + return 2; + } else if (hitValue.value >= 4) { + return 3; + } else if (hitValue.value >= 2) { + return 4; + } else { + return 5; + } } - } - case MultiHitType._2: - return 2; - case MultiHitType._3: - return 3; - case MultiHitType._10: - return 10; - case MultiHitType.BEAT_UP: - const party = user.isPlayer() ? user.scene.getParty() : user.scene.getEnemyParty(); - // No status means the ally pokemon can contribute to Beat Up - return party.reduce((total, pokemon) => { - return total + (pokemon.id === user.id ? 1 : pokemon?.status && pokemon.status.effect !== StatusEffect.NONE ? 0 : 1); - }, 0); + case MultiHitType._2: + return 2; + case MultiHitType._3: + return 3; + case MultiHitType._10: + return 10; + case MultiHitType.BEAT_UP: + const party = user.isPlayer() ? user.scene.getParty() : user.scene.getEnemyParty(); + // No status means the ally pokemon can contribute to Beat Up + return party.reduce((total, pokemon) => { + return total + (pokemon.id === user.id ? 1 : pokemon?.status && pokemon.status.effect !== StatusEffect.NONE ? 0 : 1); + }, 0); } } } @@ -2049,7 +2076,7 @@ export class StatusEffectAttr extends MoveEffectAttr { if (user !== target && target.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, target.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)) { if (move.category === MoveCategory.STATUS) { - user.scene.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(target)})); + user.scene.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(target) })); } return false; } @@ -2148,7 +2175,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr { const stolenItem = tierHeldItems[user.randSeedInt(tierHeldItems.length)]; user.scene.tryTransferHeldItemModifier(stolenItem, user, false).then(success => { if (success) { - user.scene.queueMessage(i18next.t("moveTriggers:stoleItem", {pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: stolenItem.type.name})); + user.scene.queueMessage(i18next.t("moveTriggers:stoleItem", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: stolenItem.type.name })); } resolve(success); }); @@ -2231,9 +2258,9 @@ export class RemoveHeldItemAttr extends MoveEffectAttr { target.scene.updateModifiers(target.isPlayer()); if (this.berriesOnly) { - user.scene.queueMessage(i18next.t("moveTriggers:incineratedItem", {pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: removedItem.type.name})); + user.scene.queueMessage(i18next.t("moveTriggers:incineratedItem", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: removedItem.type.name })); } else { - user.scene.queueMessage(i18next.t("moveTriggers:knockedOffItem", {pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: removedItem.type.name})); + user.scene.queueMessage(i18next.t("moveTriggers:knockedOffItem", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), itemName: removedItem.type.name })); } } @@ -2343,7 +2370,7 @@ export class StealEatBerryAttr extends EatBerryAttr { } // if the target has berries, pick a random berry and steal it this.chosenBerry = heldBerries[user.randSeedInt(heldBerries.length)]; - const message = i18next.t("battle:stealEatBerry", {pokemonName: user.name, targetName: target.name, berryName: this.chosenBerry.type.name}); + const message = i18next.t("battle:stealEatBerry", { pokemonName: user.name, targetName: target.name, berryName: this.chosenBerry.type.name }); user.scene.queueMessage(message); this.reduceBerryModifier(target); this.eatBerry(user); @@ -2622,7 +2649,7 @@ export class SunlightChargeAttr extends ChargeAttr { export class ElectroShotChargeAttr extends ChargeAttr { private statIncreaseApplied: boolean; constructor() { - super(ChargeAnim.ELECTRO_SHOT_CHARGING, i18next.t("moveTriggers:absorbedElectricity", {pokemonName: "{USER}"}), null, true); + super(ChargeAnim.ELECTRO_SHOT_CHARGING, i18next.t("moveTriggers:absorbedElectricity", { pokemonName: "{USER}" }), null, true); // Add a flag because ChargeAttr skills use themselves twice instead of once over one-to-two turns this.statIncreaseApplied = false; } @@ -2681,22 +2708,81 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr { resolve(true); }); } else { - user.scene.ui.showText(i18next.t("moveTriggers:tookMoveAttack", {pokemonName: getPokemonNameWithAffix(user.scene.getPokemonById(target.id) ?? undefined), moveName: move.name}), null, () => resolve(true)); + user.scene.ui.showText(i18next.t("moveTriggers:tookMoveAttack", { pokemonName: getPokemonNameWithAffix(user.scene.getPokemonById(target.id) ?? undefined), moveName: move.name }), null, () => resolve(true)); } }); } } +/** + * Attribute that cancels the associated move's effects when set to be combined with the user's ally's + * subsequent move this turn. Used for Grass Pledge, Water Pledge, and Fire Pledge. + * @extends OverrideMoveEffectAttr + */ +export class AwaitCombinedPledgeAttr extends OverrideMoveEffectAttr { + constructor() { + super(true); + } + /** + * If the user's ally is set to use a different move with this attribute, + * defer this move's effects for a combined move on the ally's turn. + * @param user the {@linkcode Pokemon} using this move + * @param target n/a + * @param move the {@linkcode Move} being used + * @param args + * - [0] a {@linkcode Utils.BooleanHolder} indicating whether the move's base + * effects should be overridden this turn. + * @returns `true` if base move effects were overridden; `false` otherwise + */ + override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + if (user.turnData.combiningPledge) { + // "The two moves have become one!\nIt's a combined move!" + user.scene.queueMessage(i18next.t("moveTriggers:combiningPledge")); + return false; + } + + const overridden = args[0] as Utils.BooleanHolder; + + const allyMovePhase = user.scene.findPhase((phase) => phase instanceof MovePhase && phase.pokemon.isPlayer() === user.isPlayer()); + if (allyMovePhase) { + const allyMove = allyMovePhase.move.getMove(); + if (allyMove !== move && allyMove.hasAttr(AwaitCombinedPledgeAttr)) { + [ user, allyMovePhase.pokemon ].forEach((p) => p.turnData.combiningPledge = move.id); + + // "{userPokemonName} is waiting for {allyPokemonName}'s move..." + user.scene.queueMessage(i18next.t("moveTriggers:awaitingPledge", { + userPokemonName: getPokemonNameWithAffix(user), + allyPokemonName: getPokemonNameWithAffix(allyMovePhase.pokemon) + })); + + // Move the ally's MovePhase (if needed) so that the ally moves next + const allyMovePhaseIndex = user.scene.phaseQueue.indexOf(allyMovePhase); + const firstMovePhaseIndex = user.scene.phaseQueue.findIndex((phase) => phase instanceof MovePhase); + if (allyMovePhaseIndex !== firstMovePhaseIndex) { + user.scene.prependToPhase(user.scene.phaseQueue.splice(allyMovePhaseIndex, 1)[0], MovePhase); + } + + overridden.value = true; + return true; + } + } + return false; + } +} + /** * Attribute used for moves that change stat stages - * @param stats {@linkcode BattleStat} array of stats to be changed - * @param stages stages by which to change the stats, from -6 to 6 - * @param selfTarget whether the changes are applied to the user (true) or the target (false) - * @param condition {@linkcode MoveConditionFunc} optional condition to trigger the stat change - * @param firstHitOnly whether the stat change only applies on the first hit of a multi hit move - * @param moveEffectTrigger {@linkcode MoveEffectTrigger} the trigger for the effect to take place - * @param firstTargetOnly whether, if this is a multi target move, to only apply the effect after the first target is hit, rather than once for each target - * @param lastHitOnly whether the effect should only apply after the last hit of a multi hit move + * + * @param stats {@linkcode BattleStat} Array of stat(s) to change + * @param stages How many stages to change the stat(s) by, [-6, 6] + * @param selfTarget `true` if the move is self-targetting + * @param condition {@linkcode MoveConditionFunc} Optional condition to be checked in order to apply the changes + * @param showMessage `true` to display a message; default `true` + * @param firstHitOnly `true` if only the first hit of a multi hit move should cause a stat stage change; default `false` + * @param moveEffectTrigger {@linkcode MoveEffectTrigger} When the stat change should trigger; default {@linkcode MoveEffectTrigger.HIT} + * @param firstTargetOnly `true` if a move that hits multiple pokemon should only trigger the stat change if it hits at least one pokemon, rather than once per hit pokemon; default `false` + * @param lastHitOnly `true` if the effect should only apply after the last hit of a multi hit move; default `false` + * @param effectChanceOverride Will override the move's normal secondary effect chance if specified * * @extends MoveEffectAttr * @see {@linkcode apply} @@ -2704,14 +2790,14 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr { export class StatStageChangeAttr extends MoveEffectAttr { public stats: BattleStat[]; public stages: integer; - private condition: MoveConditionFunc | null; + private condition?: MoveConditionFunc | null; private showMessage: boolean; - constructor(stats: BattleStat[], stages: integer, selfTarget?: boolean, condition?: MoveConditionFunc | null, showMessage: boolean = true, firstHitOnly: boolean = false, moveEffectTrigger: MoveEffectTrigger = MoveEffectTrigger.HIT, firstTargetOnly: boolean = false, lastHitOnly: boolean = false) { - super(selfTarget, moveEffectTrigger, firstHitOnly, lastHitOnly, firstTargetOnly); + constructor(stats: BattleStat[], stages: integer, selfTarget?: boolean, condition?: MoveConditionFunc | null, showMessage: boolean = true, firstHitOnly: boolean = false, moveEffectTrigger: MoveEffectTrigger = MoveEffectTrigger.HIT, firstTargetOnly: boolean = false, lastHitOnly: boolean = false, effectChanceOverride?: number) { + super(selfTarget, moveEffectTrigger, firstHitOnly, lastHitOnly, firstTargetOnly, effectChanceOverride); this.stats = stats; this.stages = stages; - this.condition = condition!; // TODO: is this bang correct? + this.condition = condition; this.showMessage = showMessage; } @@ -2759,26 +2845,26 @@ export class StatStageChangeAttr extends MoveEffectAttr { } let noEffect = false; switch (stat) { - case Stat.ATK: - if (this.selfTarget) { - noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.PHYSICAL); - } - break; - case Stat.DEF: - if (!this.selfTarget) { - noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.PHYSICAL); - } - break; - case Stat.SPATK: - if (this.selfTarget) { - noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.SPECIAL); - } - break; - case Stat.SPDEF: - if (!this.selfTarget) { - noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.SPECIAL); - } - break; + case Stat.ATK: + if (this.selfTarget) { + noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.PHYSICAL); + } + break; + case Stat.DEF: + if (!this.selfTarget) { + noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.PHYSICAL); + } + break; + case Stat.SPATK: + if (this.selfTarget) { + noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.SPECIAL); + } + break; + case Stat.SPDEF: + if (!this.selfTarget) { + noEffect = !user.getMoveset().find(m => m instanceof AttackMove && m.category === MoveCategory.SPECIAL); + } + break; } if (noEffect) { continue; @@ -2789,6 +2875,162 @@ export class StatStageChangeAttr extends MoveEffectAttr { } } +/** + * Attribute used to determine the Biome/Terrain-based secondary effect of Secret Power + */ +export class SecretPowerAttr extends MoveEffectAttr { + constructor() { + super(false); + } + + /** + * Used to determine if the move should apply a secondary effect based on Secret Power's 30% chance + * @returns `true` if the move's secondary effect should apply + */ + override canApply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean { + this.effectChanceOverride = move.chance; + const moveChance = this.getMoveChance(user, target, move, this.selfTarget); + if (moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) { + return true; + } else { + return false; + } + } + + /** + * Used to apply the secondary effect to the target Pokemon + * @returns `true` if a secondary effect is successfully applied + */ + override apply(user: Pokemon, target: Pokemon, move: Move, args?: any[]): boolean | Promise { + if (!super.apply(user, target, move, args)) { + return false; + } + let secondaryEffect: MoveEffectAttr; + const terrain = user.scene.arena.getTerrainType(); + if (terrain !== TerrainType.NONE) { + secondaryEffect = this.determineTerrainEffect(terrain); + } else { + const biome = user.scene.arena.biomeType; + secondaryEffect = this.determineBiomeEffect(biome); + } + // effectChanceOverride used in the application of the actual secondary effect + secondaryEffect.effectChanceOverride = 100; + return secondaryEffect.apply(user, target, move, []); + } + + /** + * Determines the secondary effect based on terrain. + * Takes precedence over biome-based effects. + * ``` + * Electric Terrain | Paralysis + * Misty Terrain | SpAtk -1 + * Grassy Terrain | Sleep + * Psychic Terrain | Speed -1 + * ``` + * @param terrain - {@linkcode TerrainType} The current terrain + * @returns the chosen secondary effect {@linkcode MoveEffectAttr} + */ + private determineTerrainEffect(terrain: TerrainType): MoveEffectAttr { + let secondaryEffect: MoveEffectAttr; + switch (terrain) { + case TerrainType.ELECTRIC: + default: + secondaryEffect = new StatusEffectAttr(StatusEffect.PARALYSIS, false); + break; + case TerrainType.MISTY: + secondaryEffect = new StatStageChangeAttr([ Stat.SPATK ], -1, false); + break; + case TerrainType.GRASSY: + secondaryEffect = new StatusEffectAttr(StatusEffect.SLEEP, false); + break; + case TerrainType.PSYCHIC: + secondaryEffect = new StatStageChangeAttr([ Stat.SPD ], -1, false); + break; + } + return secondaryEffect; + } + + /** + * Determines the secondary effect based on biome + * ``` + * Town, Metropolis, Slum, Dojo, Laboratory, Power Plant + Default | Paralysis + * Plains, Grass, Tall Grass, Forest, Jungle, Meadow | Sleep + * Swamp, Mountain, Temple, Ruins | Speed -1 + * Ice Cave, Snowy Forest | Freeze + * Volcano | Burn + * Fairy Cave | SpAtk -1 + * Desert, Construction Site, Beach, Island, Badlands | Accuracy -1 + * Sea, Lake, Seabed | Atk -1 + * Cave, Wasteland, Graveyard, Abyss, Space | Flinch + * End | Def -1 + * ``` + * @param biome - The current {@linkcode Biome} the battle is set in + * @returns the chosen secondary effect {@linkcode MoveEffectAttr} + */ + private determineBiomeEffect(biome: Biome): MoveEffectAttr { + let secondaryEffect: MoveEffectAttr; + switch (biome) { + case Biome.PLAINS: + case Biome.GRASS: + case Biome.TALL_GRASS: + case Biome.FOREST: + case Biome.JUNGLE: + case Biome.MEADOW: + secondaryEffect = new StatusEffectAttr(StatusEffect.SLEEP, false); + break; + case Biome.SWAMP: + case Biome.MOUNTAIN: + case Biome.TEMPLE: + case Biome.RUINS: + secondaryEffect = new StatStageChangeAttr([ Stat.SPD ], -1, false); + break; + case Biome.ICE_CAVE: + case Biome.SNOWY_FOREST: + secondaryEffect = new StatusEffectAttr(StatusEffect.FREEZE, false); + break; + case Biome.VOLCANO: + secondaryEffect = new StatusEffectAttr(StatusEffect.BURN, false); + break; + case Biome.FAIRY_CAVE: + secondaryEffect = new StatStageChangeAttr([ Stat.SPATK ], -1, false); + break; + case Biome.DESERT: + case Biome.CONSTRUCTION_SITE: + case Biome.BEACH: + case Biome.ISLAND: + case Biome.BADLANDS: + secondaryEffect = new StatStageChangeAttr([ Stat.ACC ], -1, false); + break; + case Biome.SEA: + case Biome.LAKE: + case Biome.SEABED: + secondaryEffect = new StatStageChangeAttr([ Stat.ATK ], -1, false); + break; + case Biome.CAVE: + case Biome.WASTELAND: + case Biome.GRAVEYARD: + case Biome.ABYSS: + case Biome.SPACE: + secondaryEffect = new AddBattlerTagAttr(BattlerTagType.FLINCHED, false, true); + break; + case Biome.END: + secondaryEffect = new StatStageChangeAttr([ Stat.DEF ], -1, false); + break; + case Biome.TOWN: + case Biome.METROPOLIS: + case Biome.SLUM: + case Biome.DOJO: + case Biome.FACTORY: + case Biome.LABORATORY: + case Biome.POWER_PLANT: + default: + secondaryEffect = new StatusEffectAttr(StatusEffect.PARALYSIS, false); + break; + } + return secondaryEffect; + } +} + export class PostVictoryStatStageChangeAttr extends MoveAttr { private stats: BattleStat[]; private stages: number; @@ -2819,7 +3061,7 @@ export class AcupressureStatStageChangeAttr extends MoveEffectAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean | Promise { const randStats = BATTLE_STATS.filter(s => target.getStatStage(s) < 6); if (randStats.length > 0) { - const boostStat = [randStats[user.randSeedInt(randStats.length)]]; + const boostStat = [ randStats[user.randSeedInt(randStats.length)] ]; user.scene.unshiftPhase(new StatStageChangePhase(user.scene, target.getBattlerIndex(), this.selfTarget, boostStat, 2)); return true; } @@ -2890,7 +3132,7 @@ export class CopyStatsAttr extends MoveEffectAttr { } target.updateInfo(); user.updateInfo(); - target.scene.queueMessage(i18next.t("moveTriggers:copiedStatChanges", {pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target)})); + target.scene.queueMessage(i18next.t("moveTriggers:copiedStatChanges", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) })); return true; } @@ -2909,7 +3151,7 @@ export class InvertStatsAttr extends MoveEffectAttr { target.updateInfo(); user.updateInfo(); - target.scene.queueMessage(i18next.t("moveTriggers:invertStats", {pokemonName: getPokemonNameWithAffix(target)})); + target.scene.queueMessage(i18next.t("moveTriggers:invertStats", { pokemonName: getPokemonNameWithAffix(target) })); return true; } @@ -2930,7 +3172,7 @@ export class ResetStatsAttr extends MoveEffectAttr { } else { // Affects only the single target when Clear Smog is used if (!move.hitsSubstitute(user, target)) { promises.push(this.resetStats(target)); - target.scene.queueMessage(i18next.t("moveTriggers:resetStats", {pokemonName: getPokemonNameWithAffix(target)})); + target.scene.queueMessage(i18next.t("moveTriggers:resetStats", { pokemonName: getPokemonNameWithAffix(target) })); } } @@ -3067,21 +3309,21 @@ export class LessPPMorePowerAttr extends VariablePowerAttr { const power = args[0] as Utils.NumberHolder; switch (ppRemains) { - case 0: - power.value = 200; - break; - case 1: - power.value = 80; - break; - case 2: - power.value = 60; - break; - case 3: - power.value = 50; - break; - default: - power.value = 40; - break; + case 0: + power.value = 200; + break; + case 1: + power.value = 80; + break; + case 2: + power.value = 60; + break; + case 3: + power.value = 50; + break; + default: + power.value = 40; + break; } return true; } @@ -3154,7 +3396,7 @@ const doublePowerChanceMessageFunc = (user: Pokemon, target: Pokemon, move: Move user.scene.executeWithSeedOffset(() => { const rand = Utils.randSeedInt(100); if (rand < move.chance) { - message = i18next.t("moveTriggers:goingAllOutForAttack", {pokemonName: getPokemonNameWithAffix(user)}); + message = i18next.t("moveTriggers:goingAllOutForAttack", { pokemonName: getPokemonNameWithAffix(user) }); } }, user.scene.currentBattle.turn << 6, user.scene.waveSeed); return message; @@ -3301,24 +3543,24 @@ export class LowHpPowerAttr extends VariablePowerAttr { const hpRatio = user.getHpRatio(); switch (true) { - case (hpRatio < 0.0417): - power.value = 200; - break; - case (hpRatio < 0.1042): - power.value = 150; - break; - case (hpRatio < 0.2083): - power.value = 100; - break; - case (hpRatio < 0.3542): - power.value = 80; - break; - case (hpRatio < 0.6875): - power.value = 40; - break; - default: - power.value = 20; - break; + case (hpRatio < 0.0417): + power.value = 200; + break; + case (hpRatio < 0.1042): + power.value = 150; + break; + case (hpRatio < 0.2083): + power.value = 100; + break; + case (hpRatio < 0.3542): + power.value = 80; + break; + case (hpRatio < 0.6875): + power.value = 40; + break; + default: + power.value = 20; + break; } return true; @@ -3338,21 +3580,21 @@ export class CompareWeightPowerAttr extends VariablePowerAttr { const relativeWeight = (targetWeight / userWeight) * 100; switch (true) { - case (relativeWeight < 20.01): - power.value = 120; - break; - case (relativeWeight < 25.01): - power.value = 100; - break; - case (relativeWeight < 33.35): - power.value = 80; - break; - case (relativeWeight < 50.01): - power.value = 60; - break; - default: - power.value = 40; - break; + case (relativeWeight < 20.01): + power.value = 120; + break; + case (relativeWeight < 25.01): + power.value = 100; + break; + case (relativeWeight < 33.35): + power.value = 80; + break; + case (relativeWeight < 50.01): + power.value = 60; + break; + default: + power.value = 40; + break; } return true; @@ -3433,7 +3675,7 @@ const magnitudeMessageFunc = (user: Pokemon, target: Pokemon, move: Move) => { } } - message = i18next.t("moveTriggers:magnitudeMessage", {magnitude: m + 4}); + message = i18next.t("moveTriggers:magnitudeMessage", { magnitude: m + 4 }); }, user.scene.currentBattle.turn << 6, user.scene.waveSeed); return message!; }; @@ -3468,13 +3710,13 @@ export class AntiSunlightPowerDecreaseAttr extends VariablePowerAttr { const power = args[0] as Utils.NumberHolder; const weatherType = user.scene.arena.weather?.weatherType || WeatherType.NONE; switch (weatherType) { - case WeatherType.RAIN: - case WeatherType.SANDSTORM: - case WeatherType.HAIL: - case WeatherType.SNOW: - case WeatherType.HEAVY_RAIN: - power.value *= 0.5; - return true; + case WeatherType.RAIN: + case WeatherType.SANDSTORM: + case WeatherType.HAIL: + case WeatherType.SNOW: + case WeatherType.HEAVY_RAIN: + power.value *= 0.5; + return true; } } @@ -3583,7 +3825,7 @@ export class PresentPowerAttr extends VariablePowerAttr { // If this move is multi-hit, disable all other hits user.stopMultiHit(); target.scene.unshiftPhase(new PokemonHealPhase(target.scene, target.getBattlerIndex(), - Utils.toDmgValue(target.getMaxHp() / 4), i18next.t("moveTriggers:regainedHealth", {pokemonName: getPokemonNameWithAffix(target)}), true)); + Utils.toDmgValue(target.getMaxHp() / 4), i18next.t("moveTriggers:regainedHealth", { pokemonName: getPokemonNameWithAffix(target) }), true)); } return true; @@ -3748,8 +3990,8 @@ export class LastMoveDoublePowerAttr extends VariablePowerAttr { for (const p of pokemonActed) { const [ lastMove ] = p.getLastXMoves(1); - if (lastMove.result !== MoveResult.FAIL) { - if ((lastMove.result === MoveResult.SUCCESS) && (lastMove.move === this.move)) { + if (lastMove?.result !== MoveResult.FAIL) { + if ((lastMove?.result === MoveResult.SUCCESS) && (lastMove?.move === this.move)) { power.value *= 2; return true; } else { @@ -3762,6 +4004,45 @@ export class LastMoveDoublePowerAttr extends VariablePowerAttr { } } +/** + * Changes a Pledge move's power to 150 when combined with another unique Pledge + * move from an ally. + */ +export class CombinedPledgePowerAttr extends VariablePowerAttr { + override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const power = args[0]; + if (!(power instanceof Utils.NumberHolder)) { + return false; + } + const combinedPledgeMove = user.turnData.combiningPledge; + + if (combinedPledgeMove && combinedPledgeMove !== move.id) { + power.value *= 150 / 80; + return true; + } + return false; + } +} + +/** + * Applies STAB to the given Pledge move if the move is part of a combined attack. + */ +export class CombinedPledgeStabBoostAttr extends MoveAttr { + override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const stabMultiplier = args[0]; + if (!(stabMultiplier instanceof Utils.NumberHolder)) { + return false; + } + const combinedPledgeMove = user.turnData.combiningPledge; + + if (combinedPledgeMove && combinedPledgeMove !== move.id) { + stabMultiplier.value = 1.5; + return true; + } + return false; + } +} + export class VariableAtkAttr extends MoveAttr { constructor() { super(); @@ -3832,14 +4113,14 @@ export class ThunderAccuracyAttr extends VariableAccuracyAttr { const accuracy = args[0] as Utils.NumberHolder; const weatherType = user.scene.arena.weather?.weatherType || WeatherType.NONE; switch (weatherType) { - case WeatherType.SUNNY: - case WeatherType.HARSH_SUN: - accuracy.value = 50; - return true; - case WeatherType.RAIN: - case WeatherType.HEAVY_RAIN: - accuracy.value = -1; - return true; + case WeatherType.SUNNY: + case WeatherType.HARSH_SUN: + accuracy.value = 50; + return true; + case WeatherType.RAIN: + case WeatherType.HEAVY_RAIN: + accuracy.value = -1; + return true; } } @@ -3858,10 +4139,10 @@ export class StormAccuracyAttr extends VariableAccuracyAttr { const accuracy = args[0] as Utils.NumberHolder; const weatherType = user.scene.arena.weather?.weatherType || WeatherType.NONE; switch (weatherType) { - case WeatherType.RAIN: - case WeatherType.HEAVY_RAIN: - accuracy.value = -1; - return true; + case WeatherType.RAIN: + case WeatherType.HEAVY_RAIN: + accuracy.value = -1; + return true; } } @@ -3999,11 +4280,11 @@ export class StatusCategoryOnAllyAttr extends VariableMoveCategoryAttr { * @param user {@linkcode Pokemon} using the move * @param target {@linkcode Pokemon} target of the move * @param move {@linkcode Move} with this attribute - * @param args [0] {@linkcode Utils.IntegerHolder} The category of the move + * @param args [0] {@linkcode Utils.NumberHolder} The category of the move * @returns true if the function succeeds */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - const category = (args[0] as Utils.IntegerHolder); + const category = (args[0] as Utils.NumberHolder); if (user.getAlly() === target) { category.value = MoveCategory.STATUS; @@ -4069,7 +4350,7 @@ export class FormChangeItemTypeAttr extends VariableMoveTypeAttr { return false; } - if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.ARCEUS) || [user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.SILVALLY)) { + if ([ user.species.speciesId, user.fusionSpecies?.speciesId ].includes(Species.ARCEUS) || [ user.species.speciesId, user.fusionSpecies?.speciesId ].includes(Species.SILVALLY)) { const form = user.species.speciesId === Species.ARCEUS || user.species.speciesId === Species.SILVALLY ? user.formIndex : user.fusionSpecies?.formIndex!; // TODO: is this bang correct? moveType.value = Type[Type[form]]; @@ -4087,25 +4368,25 @@ export class TechnoBlastTypeAttr extends VariableMoveTypeAttr { return false; } - if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.GENESECT)) { + if ([ user.species.speciesId, user.fusionSpecies?.speciesId ].includes(Species.GENESECT)) { const form = user.species.speciesId === Species.GENESECT ? user.formIndex : user.fusionSpecies?.formIndex; switch (form) { - case 1: // Shock Drive - moveType.value = Type.ELECTRIC; - break; - case 2: // Burn Drive - moveType.value = Type.FIRE; - break; - case 3: // Chill Drive - moveType.value = Type.ICE; - break; - case 4: // Douse Drive - moveType.value = Type.WATER; - break; - default: - moveType.value = Type.NORMAL; - break; + case 1: // Shock Drive + moveType.value = Type.ELECTRIC; + break; + case 2: // Burn Drive + moveType.value = Type.FIRE; + break; + case 3: // Chill Drive + moveType.value = Type.ICE; + break; + case 4: // Douse Drive + moveType.value = Type.WATER; + break; + default: + moveType.value = Type.NORMAL; + break; } return true; } @@ -4121,16 +4402,16 @@ export class AuraWheelTypeAttr extends VariableMoveTypeAttr { return false; } - if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.MORPEKO)) { + if ([ user.species.speciesId, user.fusionSpecies?.speciesId ].includes(Species.MORPEKO)) { const form = user.species.speciesId === Species.MORPEKO ? user.formIndex : user.fusionSpecies?.formIndex; switch (form) { - case 1: // Hangry Mode - moveType.value = Type.DARK; - break; - default: // Full Belly Mode - moveType.value = Type.ELECTRIC; - break; + case 1: // Hangry Mode + moveType.value = Type.DARK; + break; + default: // Full Belly Mode + moveType.value = Type.ELECTRIC; + break; } return true; } @@ -4146,19 +4427,19 @@ export class RagingBullTypeAttr extends VariableMoveTypeAttr { return false; } - if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.PALDEA_TAUROS)) { + if ([ user.species.speciesId, user.fusionSpecies?.speciesId ].includes(Species.PALDEA_TAUROS)) { const form = user.species.speciesId === Species.PALDEA_TAUROS ? user.formIndex : user.fusionSpecies?.formIndex; switch (form) { - case 1: // Blaze breed - moveType.value = Type.FIRE; - break; - case 2: // Aqua breed - moveType.value = Type.WATER; - break; - default: - moveType.value = Type.FIGHTING; - break; + case 1: // Blaze breed + moveType.value = Type.FIRE; + break; + case 2: // Aqua breed + moveType.value = Type.WATER; + break; + default: + moveType.value = Type.FIGHTING; + break; } return true; } @@ -4174,26 +4455,26 @@ export class IvyCudgelTypeAttr extends VariableMoveTypeAttr { return false; } - if ([user.species.speciesId, user.fusionSpecies?.speciesId].includes(Species.OGERPON)) { + if ([ user.species.speciesId, user.fusionSpecies?.speciesId ].includes(Species.OGERPON)) { const form = user.species.speciesId === Species.OGERPON ? user.formIndex : user.fusionSpecies?.formIndex; switch (form) { - case 1: // Wellspring Mask - case 5: // Wellspring Mask Tera - moveType.value = Type.WATER; - break; - case 2: // Hearthflame Mask - case 6: // Hearthflame Mask Tera - moveType.value = Type.FIRE; - break; - case 3: // Cornerstone Mask - case 7: // Cornerstone Mask Tera - moveType.value = Type.ROCK; - break; - case 4: // Teal Mask Tera - default: - moveType.value = Type.GRASS; - break; + case 1: // Wellspring Mask + case 5: // Wellspring Mask Tera + moveType.value = Type.WATER; + break; + case 2: // Hearthflame Mask + case 6: // Hearthflame Mask Tera + moveType.value = Type.FIRE; + break; + case 3: // Cornerstone Mask + case 7: // Cornerstone Mask Tera + moveType.value = Type.ROCK; + break; + case 4: // Teal Mask Tera + default: + moveType.value = Type.GRASS; + break; } return true; } @@ -4211,23 +4492,23 @@ export class WeatherBallTypeAttr extends VariableMoveTypeAttr { if (!user.scene.arena.weather?.isEffectSuppressed(user.scene)) { switch (user.scene.arena.weather?.weatherType) { - case WeatherType.SUNNY: - case WeatherType.HARSH_SUN: - moveType.value = Type.FIRE; - break; - case WeatherType.RAIN: - case WeatherType.HEAVY_RAIN: - moveType.value = Type.WATER; - break; - case WeatherType.SANDSTORM: - moveType.value = Type.ROCK; - break; - case WeatherType.HAIL: - case WeatherType.SNOW: - moveType.value = Type.ICE; - break; - default: - return false; + case WeatherType.SUNNY: + case WeatherType.HARSH_SUN: + moveType.value = Type.FIRE; + break; + case WeatherType.RAIN: + case WeatherType.HEAVY_RAIN: + moveType.value = Type.WATER; + break; + case WeatherType.SANDSTORM: + moveType.value = Type.ROCK; + break; + case WeatherType.HAIL: + case WeatherType.SNOW: + moveType.value = Type.ICE; + break; + default: + return false; } return true; } @@ -4262,20 +4543,20 @@ export class TerrainPulseTypeAttr extends VariableMoveTypeAttr { const currentTerrain = user.scene.arena.getTerrainType(); switch (currentTerrain) { - case TerrainType.MISTY: - moveType.value = Type.FAIRY; - break; - case TerrainType.ELECTRIC: - moveType.value = Type.ELECTRIC; - break; - case TerrainType.GRASSY: - moveType.value = Type.GRASS; - break; - case TerrainType.PSYCHIC: - moveType.value = Type.PSYCHIC; - break; - default: - return false; + case TerrainType.MISTY: + moveType.value = Type.FAIRY; + break; + case TerrainType.ELECTRIC: + moveType.value = Type.ELECTRIC; + break; + case TerrainType.GRASSY: + moveType.value = Type.GRASS; + break; + case TerrainType.PSYCHIC: + moveType.value = Type.PSYCHIC; + break; + default: + return false; } return true; } @@ -4293,17 +4574,17 @@ export class HiddenPowerTypeAttr extends VariableMoveTypeAttr { } const iv_val = Math.floor(((user.ivs[Stat.HP] & 1) - +(user.ivs[Stat.ATK] & 1) * 2 - +(user.ivs[Stat.DEF] & 1) * 4 - +(user.ivs[Stat.SPD] & 1) * 8 - +(user.ivs[Stat.SPATK] & 1) * 16 - +(user.ivs[Stat.SPDEF] & 1) * 32) * 15/63); + + (user.ivs[Stat.ATK] & 1) * 2 + + (user.ivs[Stat.DEF] & 1) * 4 + + (user.ivs[Stat.SPD] & 1) * 8 + + (user.ivs[Stat.SPATK] & 1) * 16 + + (user.ivs[Stat.SPDEF] & 1) * 32) * 15 / 63); moveType.value = [ Type.FIGHTING, Type.FLYING, Type.POISON, Type.GROUND, Type.ROCK, Type.BUG, Type.GHOST, Type.STEEL, Type.FIRE, Type.WATER, Type.GRASS, Type.ELECTRIC, - Type.PSYCHIC, Type.ICE, Type.DRAGON, Type.DARK][iv_val]; + Type.PSYCHIC, Type.ICE, Type.DRAGON, Type.DARK ][iv_val]; return true; } @@ -4358,6 +4639,47 @@ export class MatchUserTypeAttr extends VariableMoveTypeAttr { } } +/** + * Changes the type of a Pledge move based on the Pledge move combined with it. + * @extends VariableMoveTypeAttr + */ +export class CombinedPledgeTypeAttr extends VariableMoveTypeAttr { + override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const moveType = args[0]; + if (!(moveType instanceof Utils.NumberHolder)) { + return false; + } + + const combinedPledgeMove = user.turnData.combiningPledge; + if (!combinedPledgeMove) { + return false; + } + + switch (move.id) { + case Moves.FIRE_PLEDGE: + if (combinedPledgeMove === Moves.WATER_PLEDGE) { + moveType.value = Type.WATER; + return true; + } + return false; + case Moves.WATER_PLEDGE: + if (combinedPledgeMove === Moves.GRASS_PLEDGE) { + moveType.value = Type.GRASS; + return true; + } + return false; + case Moves.GRASS_PLEDGE: + if (combinedPledgeMove === Moves.FIRE_PLEDGE) { + moveType.value = Type.FIRE; + return true; + } + return false; + default: + return false; + } + } +} + export class VariableMoveTypeMultiplierAttr extends MoveAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { return false; @@ -4398,18 +4720,19 @@ export class WaterSuperEffectTypeMultiplierAttr extends VariableMoveTypeMultipli export class IceNoEffectTypeAttr extends VariableMoveTypeMultiplierAttr { /** * Checks to see if the Target is Ice-Type or not. If so, the move will have no effect. - * @param {Pokemon} user N/A - * @param {Pokemon} target Pokemon that is being checked whether Ice-Type or not. - * @param {Move} move N/A - * @param {any[]} args Sets to false if the target is Ice-Type, so it should do no damage/no effect. - * @returns {boolean} Returns true if move is successful, false if Ice-Type. + * @param user n/a + * @param target The {@linkcode Pokemon} targeted by the move + * @param move n/a + * @param args `[0]` a {@linkcode Utils.NumberHolder | NumberHolder} containing a type effectiveness multiplier + * @returns `true` if this Ice-type immunity applies; `false` otherwise */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const multiplier = args[0] as Utils.NumberHolder; if (target.isOfType(Type.ICE)) { - (args[0] as Utils.BooleanHolder).value = false; - return false; + multiplier.value = 0; + return true; } - return true; + return false; } } @@ -4494,7 +4817,7 @@ const crashDamageFunc = (user: Pokemon, move: Move) => { } user.damageAndUpdate(Utils.toDmgValue(user.getMaxHp() / 2), HitResult.OTHER, false, true); - user.scene.queueMessage(i18next.t("moveTriggers:keptGoingAndCrashed", {pokemonName: getPokemonNameWithAffix(user)})); + user.scene.queueMessage(i18next.t("moveTriggers:keptGoingAndCrashed", { pokemonName: getPokemonNameWithAffix(user) })); user.turnData.damageTaken += Utils.toDmgValue(user.getMaxHp() / 2); return true; @@ -4505,7 +4828,15 @@ export class TypelessAttr extends MoveAttr { } * Attribute used for moves which ignore redirection effects, and always target their original target, i.e. Snipe Shot * Bypasses Storm Drain, Follow Me, Ally Switch, and the like. */ -export class BypassRedirectAttr extends MoveAttr { } +export class BypassRedirectAttr extends MoveAttr { + /** `true` if this move only bypasses redirection from Abilities */ + public readonly abilitiesOnly: boolean; + + constructor(abilitiesOnly: boolean = false) { + super(); + this.abilitiesOnly = abilitiesOnly; + } +} export class FrenzyAttr extends MoveEffectAttr { constructor() { @@ -4561,7 +4892,7 @@ export class AddBattlerTagAttr extends MoveEffectAttr { } canApply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - if (!super.canApply(user, target, move, args) || (this.cancelOnFail === true && user.getLastXMoves(1)[0].result === MoveResult.FAIL)) { + if (!super.canApply(user, target, move, args) || (this.cancelOnFail === true && user.getLastXMoves(1)[0]?.result === MoveResult.FAIL)) { return false; } else { return true; @@ -4589,48 +4920,48 @@ export class AddBattlerTagAttr extends MoveEffectAttr { getTagTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): integer | void { switch (this.tagType) { - case BattlerTagType.RECHARGING: - case BattlerTagType.PERISH_SONG: - return -16; - case BattlerTagType.FLINCHED: - case BattlerTagType.CONFUSED: - case BattlerTagType.INFATUATED: - case BattlerTagType.NIGHTMARE: - case BattlerTagType.DROWSY: - case BattlerTagType.DISABLED: - case BattlerTagType.HEAL_BLOCK: - case BattlerTagType.RECEIVE_DOUBLE_DAMAGE: - return -5; - case BattlerTagType.SEEDED: - case BattlerTagType.SALT_CURED: - case BattlerTagType.CURSED: - case BattlerTagType.FRENZY: - case BattlerTagType.TRAPPED: - case BattlerTagType.BIND: - case BattlerTagType.WRAP: - case BattlerTagType.FIRE_SPIN: - case BattlerTagType.WHIRLPOOL: - case BattlerTagType.CLAMP: - case BattlerTagType.SAND_TOMB: - case BattlerTagType.MAGMA_STORM: - case BattlerTagType.SNAP_TRAP: - case BattlerTagType.THUNDER_CAGE: - case BattlerTagType.INFESTATION: - return -3; - case BattlerTagType.ENCORE: - return -2; - case BattlerTagType.MINIMIZED: - case BattlerTagType.ALWAYS_GET_HIT: - return 0; - case BattlerTagType.INGRAIN: - case BattlerTagType.IGNORE_ACCURACY: - case BattlerTagType.AQUA_RING: - return 3; - case BattlerTagType.PROTECTED: - case BattlerTagType.FLYING: - case BattlerTagType.CRIT_BOOST: - case BattlerTagType.ALWAYS_CRIT: - return 5; + case BattlerTagType.RECHARGING: + case BattlerTagType.PERISH_SONG: + return -16; + case BattlerTagType.FLINCHED: + case BattlerTagType.CONFUSED: + case BattlerTagType.INFATUATED: + case BattlerTagType.NIGHTMARE: + case BattlerTagType.DROWSY: + case BattlerTagType.DISABLED: + case BattlerTagType.HEAL_BLOCK: + case BattlerTagType.RECEIVE_DOUBLE_DAMAGE: + return -5; + case BattlerTagType.SEEDED: + case BattlerTagType.SALT_CURED: + case BattlerTagType.CURSED: + case BattlerTagType.FRENZY: + case BattlerTagType.TRAPPED: + case BattlerTagType.BIND: + case BattlerTagType.WRAP: + case BattlerTagType.FIRE_SPIN: + case BattlerTagType.WHIRLPOOL: + case BattlerTagType.CLAMP: + case BattlerTagType.SAND_TOMB: + case BattlerTagType.MAGMA_STORM: + case BattlerTagType.SNAP_TRAP: + case BattlerTagType.THUNDER_CAGE: + case BattlerTagType.INFESTATION: + return -3; + case BattlerTagType.ENCORE: + return -2; + case BattlerTagType.MINIMIZED: + case BattlerTagType.ALWAYS_GET_HIT: + return 0; + case BattlerTagType.INGRAIN: + case BattlerTagType.IGNORE_ACCURACY: + case BattlerTagType.AQUA_RING: + return 3; + case BattlerTagType.PROTECTED: + case BattlerTagType.FLYING: + case BattlerTagType.CRIT_BOOST: + case BattlerTagType.ALWAYS_CRIT: + return 5; } } @@ -4678,14 +5009,14 @@ export class GulpMissileTagAttr extends MoveEffectAttr { /** * Adds BattlerTagType from GulpMissileTag based on the Pokemon's HP ratio. - * @param {Pokemon} user The Pokemon using the move. - * @param {Pokemon} target The Pokemon being targeted by the move. - * @param {Move} move The move being used. - * @param {any[]} args Additional arguments, if any. + * @param user The Pokemon using the move. + * @param _target N/A + * @param move The move being used. + * @param _args N/A * @returns Whether the BattlerTag is applied. */ - apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean | Promise { - if (!super.apply(user, target, move, args)) { + apply(user: Pokemon, _target: Pokemon, move: Move, _args: any[]): boolean { + if (!super.apply(user, _target, move, _args)) { return false; } @@ -4760,7 +5091,7 @@ export class CurseAttr extends MoveEffectAttr { target.addTag(BattlerTagType.CURSED, 0, move.id, user.id); return true; } else { - user.scene.unshiftPhase(new StatStageChangePhase(user.scene, user.getBattlerIndex(), true, [ Stat.ATK, Stat.DEF], 1)); + user.scene.unshiftPhase(new StatStageChangePhase(user.scene, user.getBattlerIndex(), true, [ Stat.ATK, Stat.DEF ], 1)); user.scene.unshiftPhase(new StatStageChangePhase(user.scene, user.getBattlerIndex(), true, [ Stat.SPD ], -1)); return true; } @@ -4832,7 +5163,7 @@ export class ConfuseAttr extends AddBattlerTagAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { if (!this.selfTarget && target.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, target.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY)) { if (move.category === MoveCategory.STATUS) { - user.scene.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(target)})); + user.scene.queueMessage(i18next.t("moveTriggers:safeguard", { targetName: getPokemonNameWithAffix(target) })); } return false; } @@ -4892,7 +5223,7 @@ export class IgnoreAccuracyAttr extends AddBattlerTagAttr { return false; } - user.scene.queueMessage(i18next.t("moveTriggers:tookAimAtTarget", {pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target)})); + user.scene.queueMessage(i18next.t("moveTriggers:tookAimAtTarget", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) })); return true; } @@ -4908,7 +5239,7 @@ export class FaintCountdownAttr extends AddBattlerTagAttr { return false; } - user.scene.queueMessage(i18next.t("moveTriggers:faintCountdown", {pokemonName: getPokemonNameWithAffix(target), turnCount: this.turnCountMin - 1})); + user.scene.queueMessage(i18next.t("moveTriggers:faintCountdown", { pokemonName: getPokemonNameWithAffix(target), turnCount: this.turnCountMin - 1 })); return true; } @@ -4999,7 +5330,7 @@ export class AddArenaTagAttr extends MoveEffectAttr { return false; } - if ((move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) && user.getLastXMoves(1)[0].result === MoveResult.SUCCESS) { + if ((move.chance < 0 || move.chance === 100 || user.randSeedInt(100) < move.chance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { user.scene.arena.addTag(this.tagType, this.turnCount, move.id, user.id, (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY); return true; } @@ -5074,7 +5405,7 @@ export class AddArenaTrapTagHitAttr extends AddArenaTagAttr { const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const tag = user.scene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; - if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) && user.getLastXMoves(1)[0].result === MoveResult.SUCCESS) { + if ((moveChance < 0 || moveChance === 100 || user.randSeedInt(100) < moveChance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { user.scene.arena.addTag(this.tagType, 0, move.id, user.id, side); if (!tag) { return true; @@ -5191,11 +5522,37 @@ export class SwapArenaTagsAttr extends MoveEffectAttr { } - user.scene.queueMessage(i18next.t("moveTriggers:swapArenaTags", {pokemonName: getPokemonNameWithAffix(user)})); + user.scene.queueMessage(i18next.t("moveTriggers:swapArenaTags", { pokemonName: getPokemonNameWithAffix(user) })); return true; } } +/** + * Attribute that adds a secondary effect to the field when two unique Pledge moves + * are combined. The effect added varies based on the two Pledge moves combined. + */ +export class AddPledgeEffectAttr extends AddArenaTagAttr { + private readonly requiredPledge: Moves; + + constructor(tagType: ArenaTagType, requiredPledge: Moves, selfSideTarget: boolean = false) { + super(tagType, 4, false, selfSideTarget); + + this.requiredPledge = requiredPledge; + } + + override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + // TODO: add support for `HIT` effect triggering in AddArenaTagAttr to remove the need for this check + if (user.getLastXMoves(1)[0]?.result !== MoveResult.SUCCESS) { + return false; + } + + if (user.turnData.combiningPledge === this.requiredPledge) { + return super.apply(user, target, move, args); + } + return false; + } +} + /** * Attribute used for Revival Blessing. * @extends MoveEffectAttr @@ -5218,7 +5575,7 @@ export class RevivalBlessingAttr extends MoveEffectAttr { return new Promise(resolve => { // If user is player, checks if the user has fainted pokemon if (user instanceof PlayerPokemon - && user.scene.getParty().findIndex(p => p.isFainted())>-1) { + && user.scene.getParty().findIndex(p => p.isFainted()) > -1) { (user as PlayerPokemon).revivalBlessing().then(() => { resolve(true); }); @@ -5232,11 +5589,11 @@ export class RevivalBlessingAttr extends MoveEffectAttr { const slotIndex = user.scene.getEnemyParty().findIndex(p => pokemon.id === p.id); pokemon.resetStatus(); pokemon.heal(Math.min(Utils.toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); - user.scene.queueMessage(i18next.t("moveTriggers:revivalBlessing", {pokemonName: getPokemonNameWithAffix(pokemon)}), 0, true); + user.scene.queueMessage(i18next.t("moveTriggers:revivalBlessing", { pokemonName: getPokemonNameWithAffix(pokemon) }), 0, true); if (user.scene.currentBattle.double && user.scene.getEnemyParty().length > 1) { const allyPokemon = user.getAlly(); - if (slotIndex<=1) { + if (slotIndex <= 1) { user.scene.unshiftPhase(new SwitchSummonPhase(user.scene, SwitchType.SWITCH, pokemon.getFieldIndex(), slotIndex, false, false)); } else if (allyPokemon.isFainted()) { user.scene.unshiftPhase(new SwitchSummonPhase(user.scene, SwitchType.SWITCH, allyPokemon.getFieldIndex(), slotIndex, false, false)); @@ -5283,38 +5640,39 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { */ const switchOutTarget = this.selfSwitch ? user : target; if (switchOutTarget instanceof PlayerPokemon) { + // Switch out logic for the player's Pokemon if (switchOutTarget.scene.getParty().filter((p) => p.isAllowedInBattle() && !p.isOnField()).length < 1) { return false; } - switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH); if (switchOutTarget.hp > 0) { + switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH); user.scene.prependToPhase(new SwitchPhase(user.scene, this.switchType, switchOutTarget.getFieldIndex(), true, true), MoveEndPhase); return true; } return false; } else if (user.scene.currentBattle.battleType !== BattleType.WILD) { + // Switch out logic for trainer battles if (switchOutTarget.scene.getEnemyParty().filter((p) => p.isAllowedInBattle() && !p.isOnField()).length < 1) { return false; } - // Switch out logic for trainer battles - switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH); if (switchOutTarget.hp > 0) { // for opponent switching out + switchOutTarget.leaveField(this.switchType === SwitchType.SWITCH); user.scene.prependToPhase(new SwitchSummonPhase(user.scene, this.switchType, switchOutTarget.getFieldIndex(), (user.scene.currentBattle.trainer ? user.scene.currentBattle.trainer.getNextSummonIndex((switchOutTarget as EnemyPokemon).trainerSlot) : 0), false, false), MoveEndPhase); } } else { + // Switch out logic for everything else (eg: WILD battles) if (user.scene.currentBattle.waveIndex % 10 === 0) { return false; } - // Switch out logic for everything else (eg: WILD battles) - switchOutTarget.leaveField(false); - if (switchOutTarget.hp) { - user.scene.queueMessage(i18next.t("moveTriggers:fled", {pokemonName: getPokemonNameWithAffix(switchOutTarget)}), null, true, 500); + if (switchOutTarget.hp > 0) { + switchOutTarget.leaveField(false); + user.scene.queueMessage(i18next.t("moveTriggers:fled", { pokemonName: getPokemonNameWithAffix(switchOutTarget) }), null, true, 500); // in double battles redirect potential moves off fled pokemon if (switchOutTarget.scene.currentBattle.double) { @@ -5343,7 +5701,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr { getFailedText(user: Pokemon, target: Pokemon, move: Move, cancelled: Utils.BooleanHolder): string | null { const blockedByAbility = new Utils.BooleanHolder(false); applyAbAttrs(ForceSwitchOutImmunityAbAttr, target, blockedByAbility); - return blockedByAbility.value ? i18next.t("moveTriggers:cannotBeSwitchedOut", {pokemonName: getPokemonNameWithAffix(target)}) : null; + return blockedByAbility.value ? i18next.t("moveTriggers:cannotBeSwitchedOut", { pokemonName: getPokemonNameWithAffix(target) }) : null; } getSwitchOutCondition(): MoveConditionFunc { @@ -5456,7 +5814,7 @@ export class CopyTypeAttr extends MoveEffectAttr { user.summonData.types = target.getTypes(true); user.updateInfo(); - user.scene.queueMessage(i18next.t("moveTriggers:copyType", {pokemonName: getPokemonNameWithAffix(user), targetPokemonName: getPokemonNameWithAffix(target)})); + user.scene.queueMessage(i18next.t("moveTriggers:copyType", { pokemonName: getPokemonNameWithAffix(user), targetPokemonName: getPokemonNameWithAffix(target) })); return true; } @@ -5481,7 +5839,7 @@ export class CopyBiomeTypeAttr extends MoveEffectAttr { user.summonData.types = [ biomeType ]; user.updateInfo(); - user.scene.queueMessage(i18next.t("moveTriggers:transformedIntoType", {pokemonName: getPokemonNameWithAffix(user), typeName: i18next.t(`pokemonInfo:Type.${Type[biomeType]}`)})); + user.scene.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), typeName: i18next.t(`pokemonInfo:Type.${Type[biomeType]}`) })); return true; } @@ -5497,10 +5855,10 @@ export class ChangeTypeAttr extends MoveEffectAttr { } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - target.summonData.types = [this.type]; + target.summonData.types = [ this.type ]; target.updateInfo(); - user.scene.queueMessage(i18next.t("moveTriggers:transformedIntoType", {pokemonName: getPokemonNameWithAffix(target), typeName: i18next.t(`pokemonInfo:Type.${Type[this.type]}`)})); + user.scene.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(target), typeName: i18next.t(`pokemonInfo:Type.${Type[this.type]}`) })); return true; } @@ -5527,13 +5885,13 @@ export class AddTypeAttr extends MoveEffectAttr { target.summonData.types = types; target.updateInfo(); - user.scene.queueMessage(i18next.t("moveTriggers:addType", {typeName: i18next.t(`pokemonInfo:Type.${Type[this.type]}`), pokemonName: getPokemonNameWithAffix(target)})); + user.scene.queueMessage(i18next.t("moveTriggers:addType", { typeName: i18next.t(`pokemonInfo:Type.${Type[this.type]}`), pokemonName: getPokemonNameWithAffix(target) })); return true; } getCondition(): MoveConditionFunc { - return (user, target, move) => !target.isTerastallized()&& !target.getTypes().includes(this.type); + return (user, target, move) => !target.isTerastallized() && !target.getTypes().includes(this.type); } } @@ -5549,7 +5907,7 @@ export class FirstMoveTypeAttr extends MoveEffectAttr { const firstMoveType = target.getMoveset()[0]?.getMove().type!; // TODO: is this bang correct? user.summonData.types = [ firstMoveType ]; - user.scene.queueMessage(i18next.t("battle:transformedIntoType", {pokemonName: getPokemonNameWithAffix(user), type: i18next.t(`pokemonInfo:Type.${Type[firstMoveType]}`)})); + user.scene.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: i18next.t(`pokemonInfo:Type.${Type[firstMoveType]}`) })); return true; } @@ -5576,19 +5934,19 @@ export class RandomMovesetMoveAttr extends OverrideMoveEffectAttr { } let selectTargets: BattlerIndex[]; switch (true) { - case (moveTargets.multiple || moveTargets.targets.length === 1): { - selectTargets = moveTargets.targets; - break; - } - case (moveTargets.targets.indexOf(target.getBattlerIndex()) > -1): { - selectTargets = [ target.getBattlerIndex() ]; - break; - } - default: { - moveTargets.targets.splice(moveTargets.targets.indexOf(user.getAlly().getBattlerIndex())); - selectTargets = [ moveTargets.targets[user.randSeedInt(moveTargets.targets.length)] ]; - break; - } + case (moveTargets.multiple || moveTargets.targets.length === 1): { + selectTargets = moveTargets.targets; + break; + } + case (moveTargets.targets.indexOf(target.getBattlerIndex()) > -1): { + selectTargets = [ target.getBattlerIndex() ]; + break; + } + default: { + moveTargets.targets.splice(moveTargets.targets.indexOf(user.getAlly().getBattlerIndex())); + selectTargets = [ moveTargets.targets[user.randSeedInt(moveTargets.targets.length)] ]; + break; + } } const targets = selectTargets; user.getMoveQueue().push({ move: move?.moveId!, targets: targets, ignorePP: true }); // TODO: is this bang correct? @@ -5632,135 +5990,135 @@ export class NaturePowerAttr extends OverrideMoveEffectAttr { let moveId; switch (user.scene.arena.getTerrainType()) { // this allows terrains to 'override' the biome move - case TerrainType.NONE: - switch (user.scene.arena.biomeType) { - case Biome.TOWN: - moveId = Moves.ROUND; + case TerrainType.NONE: + switch (user.scene.arena.biomeType) { + case Biome.TOWN: + moveId = Moves.ROUND; + break; + case Biome.METROPOLIS: + moveId = Moves.TRI_ATTACK; + break; + case Biome.SLUM: + moveId = Moves.SLUDGE_BOMB; + break; + case Biome.PLAINS: + moveId = Moves.SILVER_WIND; + break; + case Biome.GRASS: + moveId = Moves.GRASS_KNOT; + break; + case Biome.TALL_GRASS: + moveId = Moves.POLLEN_PUFF; + break; + case Biome.MEADOW: + moveId = Moves.GIGA_DRAIN; + break; + case Biome.FOREST: + moveId = Moves.BUG_BUZZ; + break; + case Biome.JUNGLE: + moveId = Moves.LEAF_STORM; + break; + case Biome.SEA: + moveId = Moves.HYDRO_PUMP; + break; + case Biome.SWAMP: + moveId = Moves.MUD_BOMB; + break; + case Biome.BEACH: + moveId = Moves.SCALD; + break; + case Biome.LAKE: + moveId = Moves.BUBBLE_BEAM; + break; + case Biome.SEABED: + moveId = Moves.BRINE; + break; + case Biome.ISLAND: + moveId = Moves.LEAF_TORNADO; + break; + case Biome.MOUNTAIN: + moveId = Moves.AIR_SLASH; + break; + case Biome.BADLANDS: + moveId = Moves.EARTH_POWER; + break; + case Biome.DESERT: + moveId = Moves.SCORCHING_SANDS; + break; + case Biome.WASTELAND: + moveId = Moves.DRAGON_PULSE; + break; + case Biome.CONSTRUCTION_SITE: + moveId = Moves.STEEL_BEAM; + break; + case Biome.CAVE: + moveId = Moves.POWER_GEM; + break; + case Biome.ICE_CAVE: + moveId = Moves.ICE_BEAM; + break; + case Biome.SNOWY_FOREST: + moveId = Moves.FROST_BREATH; + break; + case Biome.VOLCANO: + moveId = Moves.LAVA_PLUME; + break; + case Biome.GRAVEYARD: + moveId = Moves.SHADOW_BALL; + break; + case Biome.RUINS: + moveId = Moves.ANCIENT_POWER; + break; + case Biome.TEMPLE: + moveId = Moves.EXTRASENSORY; + break; + case Biome.DOJO: + moveId = Moves.FOCUS_BLAST; + break; + case Biome.FAIRY_CAVE: + moveId = Moves.ALLURING_VOICE; + break; + case Biome.ABYSS: + moveId = Moves.OMINOUS_WIND; + break; + case Biome.SPACE: + moveId = Moves.DRACO_METEOR; + break; + case Biome.FACTORY: + moveId = Moves.FLASH_CANNON; + break; + case Biome.LABORATORY: + moveId = Moves.ZAP_CANNON; + break; + case Biome.POWER_PLANT: + moveId = Moves.CHARGE_BEAM; + break; + case Biome.END: + moveId = Moves.ETERNABEAM; + break; + } break; - case Biome.METROPOLIS: + case TerrainType.MISTY: + moveId = Moves.MOONBLAST; + break; + case TerrainType.ELECTRIC: + moveId = Moves.THUNDERBOLT; + break; + case TerrainType.GRASSY: + moveId = Moves.ENERGY_BALL; + break; + case TerrainType.PSYCHIC: + moveId = Moves.PSYCHIC; + break; + default: + // Just in case there's no match moveId = Moves.TRI_ATTACK; break; - case Biome.SLUM: - moveId = Moves.SLUDGE_BOMB; - break; - case Biome.PLAINS: - moveId = Moves.SILVER_WIND; - break; - case Biome.GRASS: - moveId = Moves.GRASS_KNOT; - break; - case Biome.TALL_GRASS: - moveId = Moves.POLLEN_PUFF; - break; - case Biome.MEADOW: - moveId = Moves.GIGA_DRAIN; - break; - case Biome.FOREST: - moveId = Moves.BUG_BUZZ; - break; - case Biome.JUNGLE: - moveId = Moves.LEAF_STORM; - break; - case Biome.SEA: - moveId = Moves.HYDRO_PUMP; - break; - case Biome.SWAMP: - moveId = Moves.MUD_BOMB; - break; - case Biome.BEACH: - moveId = Moves.SCALD; - break; - case Biome.LAKE: - moveId = Moves.BUBBLE_BEAM; - break; - case Biome.SEABED: - moveId = Moves.BRINE; - break; - case Biome.ISLAND: - moveId = Moves.LEAF_TORNADO; - break; - case Biome.MOUNTAIN: - moveId = Moves.AIR_SLASH; - break; - case Biome.BADLANDS: - moveId = Moves.EARTH_POWER; - break; - case Biome.DESERT: - moveId = Moves.SCORCHING_SANDS; - break; - case Biome.WASTELAND: - moveId = Moves.DRAGON_PULSE; - break; - case Biome.CONSTRUCTION_SITE: - moveId = Moves.STEEL_BEAM; - break; - case Biome.CAVE: - moveId = Moves.POWER_GEM; - break; - case Biome.ICE_CAVE: - moveId = Moves.ICE_BEAM; - break; - case Biome.SNOWY_FOREST: - moveId = Moves.FROST_BREATH; - break; - case Biome.VOLCANO: - moveId = Moves.LAVA_PLUME; - break; - case Biome.GRAVEYARD: - moveId = Moves.SHADOW_BALL; - break; - case Biome.RUINS: - moveId = Moves.ANCIENT_POWER; - break; - case Biome.TEMPLE: - moveId = Moves.EXTRASENSORY; - break; - case Biome.DOJO: - moveId = Moves.FOCUS_BLAST; - break; - case Biome.FAIRY_CAVE: - moveId = Moves.ALLURING_VOICE; - break; - case Biome.ABYSS: - moveId = Moves.OMINOUS_WIND; - break; - case Biome.SPACE: - moveId = Moves.DRACO_METEOR; - break; - case Biome.FACTORY: - moveId = Moves.FLASH_CANNON; - break; - case Biome.LABORATORY: - moveId = Moves.ZAP_CANNON; - break; - case Biome.POWER_PLANT: - moveId = Moves.CHARGE_BEAM; - break; - case Biome.END: - moveId = Moves.ETERNABEAM; - break; - } - break; - case TerrainType.MISTY: - moveId = Moves.MOONBLAST; - break; - case TerrainType.ELECTRIC: - moveId = Moves.THUNDERBOLT; - break; - case TerrainType.GRASSY: - moveId = Moves.ENERGY_BALL; - break; - case TerrainType.PSYCHIC: - moveId = Moves.PSYCHIC; - break; - default: - // Just in case there's no match - moveId = Moves.TRI_ATTACK; - break; } - user.getMoveQueue().push({ move: moveId, targets: [target.getBattlerIndex()], ignorePP: true }); - user.scene.unshiftPhase(new MovePhase(user.scene, user, [target.getBattlerIndex()], new PokemonMove(moveId, 0, 0, true), true)); + user.getMoveQueue().push({ move: moveId, targets: [ target.getBattlerIndex() ], ignorePP: true }); + user.scene.unshiftPhase(new MovePhase(user.scene, user, [ target.getBattlerIndex() ], new PokemonMove(moveId, 0, 0, true), true)); initMoveAnim(user.scene, moveId).then(() => { loadMoveAnimAssets(user.scene, [ moveId ], true) .then(() => resolve(true)); @@ -5838,7 +6196,7 @@ export class ReducePpMoveAttr extends MoveEffectAttr { const lastPpUsed = movesetMove?.ppUsed!; // TODO: is the bang correct? movesetMove!.ppUsed = Math.min((movesetMove?.ppUsed!) + this.reduction, movesetMove?.getMovePp()!); // TODO: is the bang correct? - const message = i18next.t("battle:ppReduced", {targetName: getPokemonNameWithAffix(target), moveName: movesetMove?.getName(), reduction: (movesetMove?.ppUsed!) - lastPpUsed}); // TODO: is the bang correct? + const message = i18next.t("battle:ppReduced", { targetName: getPokemonNameWithAffix(target), moveName: movesetMove?.getName(), reduction: (movesetMove?.ppUsed!) - lastPpUsed }); // TODO: is the bang correct? user.scene.eventTarget.dispatchEvent(new MoveUsedEvent(target?.id, movesetMove?.getMove()!, movesetMove?.ppUsed!)); // TODO: are these bangs correct? user.scene.queueMessage(message); @@ -5951,7 +6309,7 @@ export class MovesetCopyMoveAttr extends OverrideMoveEffectAttr { user.summonData.moveset = user.getMoveset().slice(0); user.summonData.moveset[thisMoveIndex] = new PokemonMove(copiedMove.id, 0, 0); - user.scene.queueMessage(i18next.t("moveTriggers:copiedMove", {pokemonName: getPokemonNameWithAffix(user), moveName: copiedMove.name})); + user.scene.queueMessage(i18next.t("moveTriggers:copiedMove", { pokemonName: getPokemonNameWithAffix(user), moveName: copiedMove.name })); return true; } @@ -6000,7 +6358,7 @@ export class SketchAttr extends MoveEffectAttr { user.setMove(sketchIndex, sketchedMove.id); - user.scene.queueMessage(i18next.t("moveTriggers:sketchedMove", {pokemonName: getPokemonNameWithAffix(user), moveName: sketchedMove.name})); + user.scene.queueMessage(i18next.t("moveTriggers:sketchedMove", { pokemonName: getPokemonNameWithAffix(user), moveName: sketchedMove.name })); return true; } @@ -6060,7 +6418,7 @@ export class AbilityChangeAttr extends MoveEffectAttr { moveTarget.summonData.ability = this.ability; user.scene.triggerPokemonFormChange(moveTarget, SpeciesFormChangeRevertWeatherFormTrigger); - user.scene.queueMessage(i18next.t("moveTriggers:acquiredAbility", {pokemonName: getPokemonNameWithAffix((this.selfTarget ? user : target)), abilityName: allAbilities[this.ability].name})); + user.scene.queueMessage(i18next.t("moveTriggers:acquiredAbility", { pokemonName: getPokemonNameWithAffix((this.selfTarget ? user : target)), abilityName: allAbilities[this.ability].name })); return true; } @@ -6086,11 +6444,11 @@ export class AbilityCopyAttr extends MoveEffectAttr { user.summonData.ability = target.getAbility().id; - user.scene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", {pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name})); + user.scene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name })); if (this.copyToPartner && user.scene.currentBattle?.double && user.getAlly().hp) { user.getAlly().summonData.ability = target.getAbility().id; - user.getAlly().scene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", {pokemonName: getPokemonNameWithAffix(user.getAlly()), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name})); + user.getAlly().scene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(user.getAlly()), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name })); } return true; @@ -6123,7 +6481,7 @@ export class AbilityGiveAttr extends MoveEffectAttr { target.summonData.ability = user.getAbility().id; - user.scene.queueMessage(i18next.t("moveTriggers:acquiredAbility", {pokemonName: getPokemonNameWithAffix(target), abilityName: allAbilities[user.getAbility().id].name})); + user.scene.queueMessage(i18next.t("moveTriggers:acquiredAbility", { pokemonName: getPokemonNameWithAffix(target), abilityName: allAbilities[user.getAbility().id].name })); return true; } @@ -6143,7 +6501,7 @@ export class SwitchAbilitiesAttr extends MoveEffectAttr { user.summonData.ability = target.getAbility().id; target.summonData.ability = tempAbilityId; - user.scene.queueMessage(i18next.t("moveTriggers:swappedAbilitiesWithTarget", {pokemonName: getPokemonNameWithAffix(user)})); + user.scene.queueMessage(i18next.t("moveTriggers:swappedAbilitiesWithTarget", { pokemonName: getPokemonNameWithAffix(user) })); // Swaps Forecast/Flower Gift from Castform/Cherrim user.scene.arena.triggerWeatherBasedFormChangesToNormal(); // Swaps Forecast/Flower Gift to Castform/Cherrim (edge case) @@ -6175,7 +6533,7 @@ export class SuppressAbilitiesAttr extends MoveEffectAttr { target.summonData.abilitySuppressed = true; target.scene.arena.triggerWeatherBasedFormChangesToNormal(); - target.scene.queueMessage(i18next.t("moveTriggers:suppressAbilities", {pokemonName: getPokemonNameWithAffix(target)})); + target.scene.queueMessage(i18next.t("moveTriggers:suppressAbilities", { pokemonName: getPokemonNameWithAffix(target) })); return true; } @@ -6228,6 +6586,9 @@ export class TransformAttr extends MoveEffectAttr { user.summonData.gender = target.getGender(); user.summonData.fusionGender = target.getFusionGender(); + // Power Trick's effect will not preserved after using Transform + user.removeTag(BattlerTagType.POWER_TRICK); + // Copy all stats (except HP) for (const s of EFFECTIVE_STATS) { user.setStat(s, target.getStat(s, false), false); @@ -6241,7 +6602,7 @@ export class TransformAttr extends MoveEffectAttr { user.summonData.moveset = target.getMoveset().map(m => new PokemonMove(m?.moveId!, m?.ppUsed, m?.ppUp)); // TODO: is this bang correct? user.summonData.types = target.getTypes(); - user.scene.queueMessage(i18next.t("moveTriggers:transformedIntoTarget", {pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target)})); + user.scene.queueMessage(i18next.t("moveTriggers:transformedIntoTarget", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target) })); user.loadAssets(false).then(() => { user.playAnim(); @@ -6441,7 +6802,7 @@ export class DestinyBondAttr extends MoveEffectAttr { * @returns true */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - user.scene.queueMessage(`${i18next.t("moveTriggers:tryingToTakeFoeDown", {pokemonName: getPokemonNameWithAffix(user)})}`); + user.scene.queueMessage(`${i18next.t("moveTriggers:tryingToTakeFoeDown", { pokemonName: getPokemonNameWithAffix(user) })}`); user.addTag(BattlerTagType.DESTINY_BOND, undefined, move.id, user.id); return true; } @@ -6531,7 +6892,7 @@ export class AttackedByItemAttr extends MoveAttr { } const itemName = heldItems[0]?.type?.name ?? "item"; - target.scene.queueMessage(i18next.t("moveTriggers:attackedByItem", {pokemonName: getPokemonNameWithAffix(target), itemName: itemName})); + target.scene.queueMessage(i18next.t("moveTriggers:attackedByItem", { pokemonName: getPokemonNameWithAffix(target), itemName: itemName })); return true; }; @@ -6570,12 +6931,12 @@ export class AfterYouAttr extends MoveEffectAttr { * @returns true */ override apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean { - user.scene.queueMessage(i18next.t("moveTriggers:afterYou", {targetName: getPokemonNameWithAffix(target)})); + user.scene.queueMessage(i18next.t("moveTriggers:afterYou", { targetName: getPokemonNameWithAffix(target) })); //Will find next acting phase of the targeted pokémon, delete it and queue it next on successful delete. const nextAttackPhase = target.scene.findPhase((phase) => phase.pokemon === target); if (nextAttackPhase && target.scene.tryRemovePhase((phase: MovePhase) => phase.pokemon === target)) { - target.scene.prependToPhase(new MovePhase(target.scene, target, [...nextAttackPhase.targets], nextAttackPhase.move), MovePhase); + target.scene.prependToPhase(new MovePhase(target.scene, target, [ ...nextAttackPhase.targets ], nextAttackPhase.move), MovePhase); } return true; @@ -6593,7 +6954,7 @@ const failIfDampCondition: MoveConditionFunc = (user, target, move) => { user.scene.getField(true).map(p=>applyAbAttrs(FieldPreventExplosiveMovesAbAttr, p, cancelled)); // Queue a message if an ability prevented usage of the move if (cancelled.value) { - user.scene.queueMessage(i18next.t("moveTriggers:cannotUseMove", {pokemonName: getPokemonNameWithAffix(user), moveName: move.name})); + user.scene.queueMessage(i18next.t("moveTriggers:cannotUseMove", { pokemonName: getPokemonNameWithAffix(user), moveName: move.name })); } return !cancelled.value; }; @@ -6691,7 +7052,7 @@ export class ResistLastMoveTypeAttr extends MoveEffectAttr { return false; } - const [targetMove] = target.getLastXMoves(1); // target's most recent move + const [ targetMove ] = target.getLastXMoves(1); // target's most recent move if (!targetMove) { return false; } @@ -6707,7 +7068,7 @@ export class ResistLastMoveTypeAttr extends MoveEffectAttr { } const type = validTypes[user.randSeedInt(validTypes.length)]; user.summonData.types = [ type ]; - user.scene.queueMessage(i18next.t("battle:transformedIntoType", {pokemonName: getPokemonNameWithAffix(user), type: Utils.toReadableString(Type[type])})); + user.scene.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: Utils.toReadableString(Type[type]) })); user.updateInfo(); return true; @@ -6766,7 +7127,7 @@ export class ExposedMoveAttr extends AddBattlerTagAttr { return false; } - user.scene.queueMessage(i18next.t("moveTriggers:exposedMove", { pokemonName: getPokemonNameWithAffix(user), targetPokemonName: getPokemonNameWithAffix(target)})); + user.scene.queueMessage(i18next.t("moveTriggers:exposedMove", { pokemonName: getPokemonNameWithAffix(user), targetPokemonName: getPokemonNameWithAffix(target) })); return true; } @@ -6791,47 +7152,47 @@ export function getMoveTargets(user: Pokemon, move: Moves): MoveTargetSet { let multiple = false; switch (moveTarget) { - case MoveTarget.USER: - case MoveTarget.PARTY: - set = [ user ]; - break; - case MoveTarget.NEAR_OTHER: - case MoveTarget.OTHER: - case MoveTarget.ALL_NEAR_OTHERS: - case MoveTarget.ALL_OTHERS: - set = (opponents.concat([ user.getAlly() ])); - multiple = moveTarget === MoveTarget.ALL_NEAR_OTHERS || moveTarget === MoveTarget.ALL_OTHERS; - break; - case MoveTarget.NEAR_ENEMY: - case MoveTarget.ALL_NEAR_ENEMIES: - case MoveTarget.ALL_ENEMIES: - case MoveTarget.ENEMY_SIDE: - set = opponents; - multiple = moveTarget !== MoveTarget.NEAR_ENEMY; - break; - case MoveTarget.RANDOM_NEAR_ENEMY: - set = [ opponents[user.randSeedInt(opponents.length)] ]; - break; - case MoveTarget.ATTACKER: - return { targets: [ -1 as BattlerIndex ], multiple: false }; - case MoveTarget.NEAR_ALLY: - case MoveTarget.ALLY: - set = [ user.getAlly() ]; - break; - case MoveTarget.USER_OR_NEAR_ALLY: - case MoveTarget.USER_AND_ALLIES: - case MoveTarget.USER_SIDE: - set = [ user, user.getAlly() ]; - multiple = moveTarget !== MoveTarget.USER_OR_NEAR_ALLY; - break; - case MoveTarget.ALL: - case MoveTarget.BOTH_SIDES: - set = [ user, user.getAlly() ].concat(opponents); - multiple = true; - break; - case MoveTarget.CURSE: - set = user.getTypes(true).includes(Type.GHOST) ? (opponents.concat([ user.getAlly() ])) : [ user ]; - break; + case MoveTarget.USER: + case MoveTarget.PARTY: + set = [ user ]; + break; + case MoveTarget.NEAR_OTHER: + case MoveTarget.OTHER: + case MoveTarget.ALL_NEAR_OTHERS: + case MoveTarget.ALL_OTHERS: + set = (opponents.concat([ user.getAlly() ])); + multiple = moveTarget === MoveTarget.ALL_NEAR_OTHERS || moveTarget === MoveTarget.ALL_OTHERS; + break; + case MoveTarget.NEAR_ENEMY: + case MoveTarget.ALL_NEAR_ENEMIES: + case MoveTarget.ALL_ENEMIES: + case MoveTarget.ENEMY_SIDE: + set = opponents; + multiple = moveTarget !== MoveTarget.NEAR_ENEMY; + break; + case MoveTarget.RANDOM_NEAR_ENEMY: + set = [ opponents[user.randSeedInt(opponents.length)] ]; + break; + case MoveTarget.ATTACKER: + return { targets: [ -1 as BattlerIndex ], multiple: false }; + case MoveTarget.NEAR_ALLY: + case MoveTarget.ALLY: + set = [ user.getAlly() ]; + break; + case MoveTarget.USER_OR_NEAR_ALLY: + case MoveTarget.USER_AND_ALLIES: + case MoveTarget.USER_SIDE: + set = [ user, user.getAlly() ]; + multiple = moveTarget !== MoveTarget.USER_OR_NEAR_ALLY; + break; + case MoveTarget.ALL: + case MoveTarget.BOTH_SIDES: + set = [ user, user.getAlly() ].concat(opponents); + multiple = true; + break; + case MoveTarget.CURSE: + set = user.getTypes(true).includes(Type.GHOST) ? (opponents.concat([ user.getAlly() ])) : [ user ]; + break; } return { targets: set.filter(p => p?.isActive(true)).map(p => p.getBattlerIndex()).filter(t => t !== undefined), multiple }; @@ -6873,7 +7234,7 @@ export function initMoves() { .attr(OneHitKOAttr) .attr(OneHitKOAccuracyAttr), new AttackMove(Moves.RAZOR_WIND, Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 1) - .attr(ChargeAttr, ChargeAnim.RAZOR_WIND_CHARGING, i18next.t("moveTriggers:whippedUpAWhirlwind", {pokemonName: "{USER}"})) + .attr(ChargeAttr, ChargeAnim.RAZOR_WIND_CHARGING, i18next.t("moveTriggers:whippedUpAWhirlwind", { pokemonName: "{USER}" })) .attr(HighCritAttr) .windMove() .ignoresVirtual() @@ -6891,9 +7252,10 @@ export function initMoves() { .attr(ForceSwitchOutAttr) .ignoresSubstitute() .hidesTarget() - .windMove(), + .windMove() + .partial(), // Should force random switches new AttackMove(Moves.FLY, Type.FLYING, MoveCategory.PHYSICAL, 90, 95, 15, -1, 0, 1) - .attr(ChargeAttr, ChargeAnim.FLY_CHARGING, i18next.t("moveTriggers:flewUpHigh", {pokemonName: "{USER}"}), BattlerTagType.FLYING) + .attr(ChargeAttr, ChargeAnim.FLY_CHARGING, i18next.t("moveTriggers:flewUpHigh", { pokemonName: "{USER}" }), BattlerTagType.FLYING) .condition(failOnGravityCondition) .ignoresVirtual(), new AttackMove(Moves.BIND, Type.NORMAL, MoveCategory.PHYSICAL, 15, 85, 20, -1, 0, 1) @@ -6968,7 +7330,8 @@ export function initMoves() { new StatusMove(Moves.ROAR, Type.NORMAL, -1, 20, -1, -6, 1) .attr(ForceSwitchOutAttr) .soundBased() - .hidesTarget(), + .hidesTarget() + .partial(), // Should force random switching new StatusMove(Moves.SING, Type.NORMAL, 55, 15, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.SLEEP) .soundBased(), @@ -7042,7 +7405,7 @@ export function initMoves() { .slicingMove() .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.SOLAR_BEAM, Type.GRASS, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 1) - .attr(SunlightChargeAttr, ChargeAnim.SOLAR_BEAM_CHARGING, i18next.t("moveTriggers:tookInSunlight", {pokemonName: "{USER}"})) + .attr(SunlightChargeAttr, ChargeAnim.SOLAR_BEAM_CHARGING, i18next.t("moveTriggers:tookInSunlight", { pokemonName: "{USER}" })) .attr(AntiSunlightPowerDecreaseAttr) .ignoresVirtual(), new StatusMove(Moves.POISON_POWDER, Type.POISON, 75, 35, -1, 0, 1) @@ -7092,7 +7455,7 @@ export function initMoves() { .attr(HitsTagAttr, BattlerTagType.UNDERGROUND) .makesContact(false), new AttackMove(Moves.DIG, Type.GROUND, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 1) - .attr(ChargeAttr, ChargeAnim.DIG_CHARGING, i18next.t("moveTriggers:dugAHole", {pokemonName: "{USER}"}), BattlerTagType.UNDERGROUND) + .attr(ChargeAttr, ChargeAnim.DIG_CHARGING, i18next.t("moveTriggers:dugAHole", { pokemonName: "{USER}" }), BattlerTagType.UNDERGROUND) .ignoresVirtual(), new StatusMove(Moves.TOXIC, Type.POISON, 90, 10, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.TOXIC) @@ -7109,7 +7472,7 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.SPD ], 2, true), new AttackMove(Moves.QUICK_ATTACK, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 30, -1, 1, 1), new AttackMove(Moves.RAGE, Type.NORMAL, MoveCategory.PHYSICAL, 20, 100, 20, -1, 0, 1) - .partial(), + .partial(), // No effect implemented new SelfStatusMove(Moves.TELEPORT, Type.PSYCHIC, -1, 20, -1, -6, 1) .attr(ForceSwitchOutAttr, true) .hidesUser(), @@ -7189,7 +7552,7 @@ export function initMoves() { new AttackMove(Moves.SWIFT, Type.NORMAL, MoveCategory.SPECIAL, 60, -1, 20, -1, 0, 1) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.SKULL_BASH, Type.NORMAL, MoveCategory.PHYSICAL, 130, 100, 10, -1, 0, 1) - .attr(ChargeAttr, ChargeAnim.SKULL_BASH_CHARGING, i18next.t("moveTriggers:loweredItsHead", {pokemonName: "{USER}"}), null, true) + .attr(ChargeAttr, ChargeAnim.SKULL_BASH_CHARGING, i18next.t("moveTriggers:loweredItsHead", { pokemonName: "{USER}" }), null, true) .attr(StatStageChangeAttr, [ Stat.DEF ], 1, true) .ignoresVirtual(), new AttackMove(Moves.SPIKE_CANNON, Type.NORMAL, MoveCategory.PHYSICAL, 20, 100, 15, -1, 0, 1) @@ -7228,7 +7591,7 @@ export function initMoves() { new StatusMove(Moves.LOVELY_KISS, Type.NORMAL, 75, 10, -1, 0, 1) .attr(StatusEffectAttr, StatusEffect.SLEEP), new AttackMove(Moves.SKY_ATTACK, Type.FLYING, MoveCategory.PHYSICAL, 140, 90, 5, 30, 0, 1) - .attr(ChargeAttr, ChargeAnim.SKY_ATTACK_CHARGING, i18next.t("moveTriggers:isGlowing", {pokemonName: "{USER}"})) + .attr(ChargeAttr, ChargeAnim.SKY_ATTACK_CHARGING, i18next.t("moveTriggers:isGlowing", { pokemonName: "{USER}" })) .attr(HighCritAttr) .attr(FlinchAttr) .makesContact(false) @@ -7282,7 +7645,7 @@ export function initMoves() { new SelfStatusMove(Moves.CONVERSION, Type.NORMAL, -1, 30, -1, 0, 1) .attr(FirstMoveTypeAttr), new AttackMove(Moves.TRI_ATTACK, Type.NORMAL, MoveCategory.SPECIAL, 80, 100, 10, 20, 0, 1) - .attr(MultiStatusEffectAttr, [StatusEffect.BURN, StatusEffect.FREEZE, StatusEffect.PARALYSIS]), + .attr(MultiStatusEffectAttr, [ StatusEffect.BURN, StatusEffect.FREEZE, StatusEffect.PARALYSIS ]), new AttackMove(Moves.SUPER_FANG, Type.NORMAL, MoveCategory.PHYSICAL, -1, 90, 10, -1, 0, 1) .attr(TargetHalfHpDamageAttr), new AttackMove(Moves.SLASH, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, -1, 0, 1) @@ -7424,7 +7787,7 @@ export function initMoves() { new StatusMove(Moves.CHARM, Type.FAIRY, 100, 20, -1, 0, 2) .attr(StatStageChangeAttr, [ Stat.ATK ], -2), new AttackMove(Moves.ROLLOUT, Type.ROCK, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 2) - .partial() + .partial() // Does not lock the user, also does not increase damage properly .attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL), new AttackMove(Moves.FALSE_SWIPE, Type.NORMAL, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 2) .attr(SurviveDamageAttr), @@ -7495,7 +7858,7 @@ export function initMoves() { .ignoresSubstitute() .condition((user, target, move) => new EncoreTag(user.id).canAdd(target)), new AttackMove(Moves.PURSUIT, Type.DARK, MoveCategory.PHYSICAL, 40, 100, 20, -1, 0, 2) - .partial(), + .partial(), // No effect implemented new AttackMove(Moves.RAPID_SPIN, Type.NORMAL, MoveCategory.PHYSICAL, 50, 100, 40, 100, 0, 2) .attr(StatStageChangeAttr, [ Stat.SPD ], 1, true) .attr(RemoveBattlerTagAttr, [ @@ -7560,8 +7923,8 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.SPDEF ], -1) .ballBombMove(), new AttackMove(Moves.FUTURE_SIGHT, Type.PSYCHIC, MoveCategory.SPECIAL, 120, 100, 10, -1, 0, 2) - .partial() - .attr(DelayedAttackAttr, ArenaTagType.FUTURE_SIGHT, ChargeAnim.FUTURE_SIGHT_CHARGING, i18next.t("moveTriggers:foresawAnAttack", {pokemonName: "{USER}"})), + .partial() // Complete buggy mess + .attr(DelayedAttackAttr, ArenaTagType.FUTURE_SIGHT, ChargeAnim.FUTURE_SIGHT_CHARGING, i18next.t("moveTriggers:foresawAnAttack", { pokemonName: "{USER}" })), new AttackMove(Moves.ROCK_SMASH, Type.FIGHTING, MoveCategory.PHYSICAL, 40, 100, 15, 50, 0, 2) .attr(StatStageChangeAttr, [ Stat.DEF ], -1), new AttackMove(Moves.WHIRLPOOL, Type.WATER, MoveCategory.SPECIAL, 35, 85, 15, -1, 0, 2) @@ -7578,18 +7941,18 @@ export function initMoves() { .ignoresVirtual() .soundBased() .target(MoveTarget.RANDOM_NEAR_ENEMY) - .partial(), + .partial(), // Does not lock the user, does not stop Pokemon from sleeping new SelfStatusMove(Moves.STOCKPILE, Type.NORMAL, -1, 20, -1, 0, 3) .condition(user => (user.getTag(StockpilingTag)?.stockpiledCount ?? 0) < 3) .attr(AddBattlerTagAttr, BattlerTagType.STOCKPILING, true), new AttackMove(Moves.SPIT_UP, Type.NORMAL, MoveCategory.SPECIAL, -1, -1, 10, -1, 0, 3) .condition(hasStockpileStacksCondition) .attr(SpitUpPowerAttr, 100) - .attr(RemoveBattlerTagAttr, [BattlerTagType.STOCKPILING], true), + .attr(RemoveBattlerTagAttr, [ BattlerTagType.STOCKPILING ], true), new SelfStatusMove(Moves.SWALLOW, Type.NORMAL, -1, 10, -1, 0, 3) .condition(hasStockpileStacksCondition) .attr(SwallowHealAttr) - .attr(RemoveBattlerTagAttr, [BattlerTagType.STOCKPILING], true) + .attr(RemoveBattlerTagAttr, [ BattlerTagType.STOCKPILING ], true) .triageMove(), new AttackMove(Moves.HEAT_WAVE, Type.FIRE, MoveCategory.SPECIAL, 95, 90, 10, 10, 0, 3) .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE) @@ -7601,7 +7964,7 @@ export function initMoves() { .target(MoveTarget.BOTH_SIDES), new StatusMove(Moves.TORMENT, Type.DARK, 100, 15, -1, 0, 3) .ignoresSubstitute() - .partial() // Incomplete implementation because of Uproar's partial implementation + .edgeCase() // Incomplete implementation because of Uproar's partial implementation .attr(AddBattlerTagAttr, BattlerTagType.TORMENT, false, true, 1), new StatusMove(Moves.FLATTER, Type.DARK, 100, 15, -1, 0, 3) .attr(StatStageChangeAttr, [ Stat.SPATK ], 1) @@ -7616,7 +7979,7 @@ export function initMoves() { && (user.status.effect === StatusEffect.BURN || user.status.effect === StatusEffect.POISON || user.status.effect === StatusEffect.TOXIC || user.status.effect === StatusEffect.PARALYSIS) ? 2 : 1) .attr(BypassBurnDamageReductionAttr), new AttackMove(Moves.FOCUS_PUNCH, Type.FIGHTING, MoveCategory.PHYSICAL, 150, 100, 20, -1, -3, 3) - .attr(MessageHeaderAttr, (user, move) => i18next.t("moveTriggers:isTighteningFocus", {pokemonName: getPokemonNameWithAffix(user)})) + .attr(MessageHeaderAttr, (user, move) => i18next.t("moveTriggers:isTighteningFocus", { pokemonName: getPokemonNameWithAffix(user) })) .punchingMove() .ignoresVirtual() .condition((user, target, move) => !user.turnData.attacksReceived.find(r => r.damage)), @@ -7650,7 +8013,9 @@ export function initMoves() { .attr(RandomMovesetMoveAttr, true) .ignoresVirtual(), new SelfStatusMove(Moves.INGRAIN, Type.GRASS, -1, 20, -1, 0, 3) - .attr(AddBattlerTagAttr, BattlerTagType.INGRAIN, true, true), + .attr(AddBattlerTagAttr, BattlerTagType.INGRAIN, true, true) + .attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, true, true) + .attr(RemoveBattlerTagAttr, [ BattlerTagType.FLOATING ], true), new AttackMove(Moves.SUPERPOWER, Type.FIGHTING, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 3) .attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF ], -1, true), new SelfStatusMove(Moves.MAGIC_COAT, Type.PSYCHIC, -1, 15, -1, 4, 3) @@ -7678,7 +8043,8 @@ export function initMoves() { .attr(SwitchAbilitiesAttr), new StatusMove(Moves.IMPRISON, Type.PSYCHIC, 100, 10, -1, 0, 3) .ignoresSubstitute() - .attr(AddArenaTagAttr, ArenaTagType.IMPRISON, 1, true, false), + .attr(AddArenaTagAttr, ArenaTagType.IMPRISON, 1, true, false) + .target(MoveTarget.ENEMY_SIDE), new SelfStatusMove(Moves.REFRESH, Type.NORMAL, -1, 20, -1, 0, 3) .attr(HealStatusEffectAttr, true, StatusEffect.PARALYSIS, StatusEffect.POISON, StatusEffect.TOXIC, StatusEffect.BURN) .condition((user, target, move) => !!user.status && (user.status.effect === StatusEffect.PARALYSIS || user.status.effect === StatusEffect.POISON || user.status.effect === StatusEffect.TOXIC || user.status.effect === StatusEffect.BURN)), @@ -7688,9 +8054,9 @@ export function initMoves() { .unimplemented(), new AttackMove(Moves.SECRET_POWER, Type.NORMAL, MoveCategory.PHYSICAL, 70, 100, 20, 30, 0, 3) .makesContact(false) - .partial(), + .attr(SecretPowerAttr), new AttackMove(Moves.DIVE, Type.WATER, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 3) - .attr(ChargeAttr, ChargeAnim.DIVE_CHARGING, i18next.t("moveTriggers:hidUnderwater", {pokemonName: "{USER}"}), BattlerTagType.UNDERWATER, true) + .attr(ChargeAttr, ChargeAnim.DIVE_CHARGING, i18next.t("moveTriggers:hidUnderwater", { pokemonName: "{USER}" }), BattlerTagType.UNDERWATER, true) .attr(GulpMissileTagAttr) .ignoresVirtual(), new AttackMove(Moves.ARM_THRUST, Type.FIGHTING, MoveCategory.PHYSICAL, 15, 100, 20, -1, 0, 3) @@ -7719,7 +8085,7 @@ export function initMoves() { .attr(AddArenaTagAttr, ArenaTagType.MUD_SPORT, 5) .target(MoveTarget.BOTH_SIDES), new AttackMove(Moves.ICE_BALL, Type.ICE, MoveCategory.PHYSICAL, 30, 90, 20, -1, 0, 3) - .partial() + .partial() // Does not lock the user properly, does not increase damage correctly .attr(ConsecutiveUseDoublePowerAttr, 5, true, true, Moves.DEFENSE_CURL) .ballBombMove(), new AttackMove(Moves.NEEDLE_ARM, Type.GRASS, MoveCategory.PHYSICAL, 60, 100, 15, 30, 0, 3) @@ -7746,7 +8112,7 @@ export function initMoves() { .attr(FlinchAttr), new AttackMove(Moves.WEATHER_BALL, Type.NORMAL, MoveCategory.SPECIAL, 50, 100, 10, -1, 0, 3) .attr(WeatherBallTypeAttr) - .attr(MovePowerMultiplierAttr, (user, target, move) => [WeatherType.SUNNY, WeatherType.RAIN, WeatherType.SANDSTORM, WeatherType.HAIL, WeatherType.SNOW, WeatherType.FOG, WeatherType.HEAVY_RAIN, WeatherType.HARSH_SUN].includes(user.scene.arena.weather?.weatherType!) && !user.scene.arena.weather?.isEffectSuppressed(user.scene) ? 2 : 1) // TODO: is this bang correct? + .attr(MovePowerMultiplierAttr, (user, target, move) => [ WeatherType.SUNNY, WeatherType.RAIN, WeatherType.SANDSTORM, WeatherType.HAIL, WeatherType.SNOW, WeatherType.FOG, WeatherType.HEAVY_RAIN, WeatherType.HARSH_SUN ].includes(user.scene.arena.weather?.weatherType!) && !user.scene.arena.weather?.isEffectSuppressed(user.scene) ? 2 : 1) // TODO: is this bang correct? .ballBombMove(), new StatusMove(Moves.AROMATHERAPY, Type.GRASS, -1, 5, -1, 0, 3) .attr(PartyStatusCureAttr, i18next.t("moveTriggers:soothingAromaWaftedThroughArea"), Abilities.SAP_SIPPER) @@ -7825,7 +8191,7 @@ export function initMoves() { new SelfStatusMove(Moves.BULK_UP, Type.FIGHTING, -1, 20, -1, 0, 3) .attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF ], 1, true), new AttackMove(Moves.BOUNCE, Type.FLYING, MoveCategory.PHYSICAL, 85, 85, 5, 30, 0, 3) - .attr(ChargeAttr, ChargeAnim.BOUNCE_CHARGING, i18next.t("moveTriggers:sprangUp", {pokemonName: "{USER}"}), BattlerTagType.FLYING) + .attr(ChargeAttr, ChargeAnim.BOUNCE_CHARGING, i18next.t("moveTriggers:sprangUp", { pokemonName: "{USER}" }), BattlerTagType.FLYING) .attr(StatusEffectAttr, StatusEffect.PARALYSIS) .condition(failOnGravityCondition) .ignoresVirtual(), @@ -7862,8 +8228,8 @@ export function initMoves() { .attr(ConfuseAttr) .pulseMove(), new AttackMove(Moves.DOOM_DESIRE, Type.STEEL, MoveCategory.SPECIAL, 140, 100, 5, -1, 0, 3) - .partial() - .attr(DelayedAttackAttr, ArenaTagType.DOOM_DESIRE, ChargeAnim.DOOM_DESIRE_CHARGING, i18next.t("moveTriggers:choseDoomDesireAsDestiny", {pokemonName: "{USER}"})), + .partial() // Complete buggy mess + .attr(DelayedAttackAttr, ArenaTagType.DOOM_DESIRE, ChargeAnim.DOOM_DESIRE_CHARGING, i18next.t("moveTriggers:choseDoomDesireAsDestiny", { pokemonName: "{USER}" })), new AttackMove(Moves.PSYCHO_BOOST, Type.PSYCHIC, MoveCategory.SPECIAL, 140, 90, 5, -1, 0, 3) .attr(StatStageChangeAttr, [ Stat.SPATK ], -2, true), new SelfStatusMove(Moves.ROOST, Type.FLYING, -1, 5, -1, 0, 4) @@ -7946,7 +8312,7 @@ export function initMoves() { .attr(OpponentHighHpPowerAttr, 120) .makesContact(), new SelfStatusMove(Moves.POWER_TRICK, Type.PSYCHIC, -1, 10, -1, 0, 4) - .unimplemented(), + .attr(AddBattlerTagAttr, BattlerTagType.POWER_TRICK, true), new StatusMove(Moves.GASTRO_ACID, Type.POISON, 100, 10, -1, 0, 4) .attr(SuppressAbilitiesAttr), new StatusMove(Moves.LUCKY_CHANT, Type.NORMAL, -1, 30, -1, 0, 4) @@ -7984,8 +8350,8 @@ export function initMoves() { new SelfStatusMove(Moves.AQUA_RING, Type.WATER, -1, 20, -1, 0, 4) .attr(AddBattlerTagAttr, BattlerTagType.AQUA_RING, true, true), new SelfStatusMove(Moves.MAGNET_RISE, Type.ELECTRIC, -1, 10, -1, 0, 4) - .attr(AddBattlerTagAttr, BattlerTagType.MAGNET_RISEN, true, true) - .condition((user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY) && [BattlerTagType.MAGNET_RISEN, BattlerTagType.IGNORE_FLYING, BattlerTagType.INGRAIN].every((tag) => !user.getTag(tag))), + .attr(AddBattlerTagAttr, BattlerTagType.FLOATING, true, true) + .condition((user, target, move) => !user.scene.arena.getTag(ArenaTagType.GRAVITY) && [ BattlerTagType.FLOATING, BattlerTagType.IGNORE_FLYING, BattlerTagType.INGRAIN ].every((tag) => !user.getTag(tag))), new AttackMove(Moves.FLARE_BLITZ, Type.FIRE, MoveCategory.PHYSICAL, 120, 100, 15, 10, 0, 4) .attr(RecoilAttr, false, 0.33) .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE) @@ -8181,7 +8547,7 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true) .windMove(), new AttackMove(Moves.SHADOW_FORCE, Type.GHOST, MoveCategory.PHYSICAL, 120, 100, 5, -1, 0, 4) - .attr(ChargeAttr, ChargeAnim.SHADOW_FORCE_CHARGING, i18next.t("moveTriggers:vanishedInstantly", {pokemonName: "{USER}"}), BattlerTagType.HIDDEN) + .attr(ChargeAttr, ChargeAnim.SHADOW_FORCE_CHARGING, i18next.t("moveTriggers:vanishedInstantly", { pokemonName: "{USER}" }), BattlerTagType.HIDDEN) .ignoresProtect() .ignoresVirtual(), new SelfStatusMove(Moves.HONE_CLAWS, Type.DARK, -1, 15, -1, 0, 5) @@ -8210,7 +8576,11 @@ export function initMoves() { .attr(AddBattlerTagAttr, BattlerTagType.CENTER_OF_ATTENTION, true), new StatusMove(Moves.TELEKINESIS, Type.PSYCHIC, -1, 15, -1, 0, 5) .condition(failOnGravityCondition) - .unimplemented(), + .condition((_user, target, _move) => ![ Species.DIGLETT, Species.DUGTRIO, Species.ALOLA_DIGLETT, Species.ALOLA_DUGTRIO, Species.SANDYGAST, Species.PALOSSAND, Species.WIGLETT, Species.WUGTRIO ].includes(target.species.speciesId)) + .condition((_user, target, _move) => !(target.species.speciesId === Species.GENGAR && target.getFormKey() === "mega")) + .condition((_user, target, _move) => Utils.isNullOrUndefined(target.getTag(BattlerTagType.INGRAIN)) && Utils.isNullOrUndefined(target.getTag(BattlerTagType.IGNORE_FLYING))) + .attr(AddBattlerTagAttr, BattlerTagType.TELEKINESIS, false, true, 3) + .attr(AddBattlerTagAttr, BattlerTagType.FLOATING, false, true, 3), new StatusMove(Moves.MAGIC_ROOM, Type.PSYCHIC, -1, 10, -1, 0, 5) .ignoresProtect() .target(MoveTarget.BOTH_SIDES) @@ -8218,7 +8588,7 @@ export function initMoves() { new AttackMove(Moves.SMACK_DOWN, Type.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5) .attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true) .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) - .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN]) + .attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.FLOATING, BattlerTagType.TELEKINESIS ]) .attr(HitsTagAttr, BattlerTagType.FLYING) .makesContact(false), new AttackMove(Moves.STORM_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5) @@ -8268,7 +8638,7 @@ export function initMoves() { .attr(AfterYouAttr), new AttackMove(Moves.ROUND, Type.NORMAL, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5) .soundBased() - .partial(), + .partial(), // No effect implemented new AttackMove(Moves.ECHOED_VOICE, Type.NORMAL, MoveCategory.SPECIAL, 40, 100, 15, -1, 0, 5) .attr(ConsecutiveUseMultiBasePowerAttr, 5, false) .soundBased(), @@ -8299,10 +8669,10 @@ export function initMoves() { new AttackMove(Moves.HEX, Type.GHOST, MoveCategory.SPECIAL, 65, 100, 10, -1, 0, 5) .attr( MovePowerMultiplierAttr, - (user, target, move) => target.status || target.hasAbility(Abilities.COMATOSE)? 2 : 1), + (user, target, move) => target.status || target.hasAbility(Abilities.COMATOSE) ? 2 : 1), new AttackMove(Moves.SKY_DROP, Type.FLYING, MoveCategory.PHYSICAL, 60, 100, 10, -1, 0, 5) .partial() // Should immobilize the target, Flying types should take no damage. cf https://bulbapedia.bulbagarden.net/wiki/Sky_Drop_(move) and https://www.smogon.com/dex/sv/moves/sky-drop/ - .attr(ChargeAttr, ChargeAnim.SKY_DROP_CHARGING, i18next.t("moveTriggers:tookTargetIntoSky", {pokemonName: "{USER}", targetName: "{TARGET}"}), BattlerTagType.FLYING) // TODO: Add 2nd turn message + .attr(ChargeAttr, ChargeAnim.SKY_DROP_CHARGING, i18next.t("moveTriggers:tookTargetIntoSky", { pokemonName: "{USER}", targetName: "{TARGET}" }), BattlerTagType.FLYING) // TODO: Add 2nd turn message .condition(failOnGravityCondition) .condition((user, target, move) => !target.getTag(BattlerTagType.SUBSTITUTE)) .ignoresVirtual(), @@ -8310,7 +8680,8 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.ATK ], 1, true) .attr(StatStageChangeAttr, [ Stat.SPD ], 2, true), new AttackMove(Moves.CIRCLE_THROW, Type.FIGHTING, MoveCategory.PHYSICAL, 60, 90, 10, -1, -6, 5) - .attr(ForceSwitchOutAttr), + .attr(ForceSwitchOutAttr) + .partial(), // Should force random switches new AttackMove(Moves.INCINERATE, Type.FIRE, MoveCategory.SPECIAL, 60, 100, 15, -1, 0, 5) .target(MoveTarget.ALL_NEAR_ENEMIES) .attr(RemoveHeldItemAttr, true), @@ -8341,11 +8712,29 @@ export function initMoves() { new AttackMove(Moves.INFERNO, Type.FIRE, MoveCategory.SPECIAL, 100, 50, 5, 100, 0, 5) .attr(StatusEffectAttr, StatusEffect.BURN), new AttackMove(Moves.WATER_PLEDGE, Type.WATER, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 5) - .partial(), + .attr(AwaitCombinedPledgeAttr) + .attr(CombinedPledgeTypeAttr) + .attr(CombinedPledgePowerAttr) + .attr(CombinedPledgeStabBoostAttr) + .attr(AddPledgeEffectAttr, ArenaTagType.WATER_FIRE_PLEDGE, Moves.FIRE_PLEDGE, true) + .attr(AddPledgeEffectAttr, ArenaTagType.GRASS_WATER_PLEDGE, Moves.GRASS_PLEDGE) + .attr(BypassRedirectAttr, true), new AttackMove(Moves.FIRE_PLEDGE, Type.FIRE, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 5) - .partial(), + .attr(AwaitCombinedPledgeAttr) + .attr(CombinedPledgeTypeAttr) + .attr(CombinedPledgePowerAttr) + .attr(CombinedPledgeStabBoostAttr) + .attr(AddPledgeEffectAttr, ArenaTagType.FIRE_GRASS_PLEDGE, Moves.GRASS_PLEDGE) + .attr(AddPledgeEffectAttr, ArenaTagType.WATER_FIRE_PLEDGE, Moves.WATER_PLEDGE, true) + .attr(BypassRedirectAttr, true), new AttackMove(Moves.GRASS_PLEDGE, Type.GRASS, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 5) - .partial(), + .attr(AwaitCombinedPledgeAttr) + .attr(CombinedPledgeTypeAttr) + .attr(CombinedPledgePowerAttr) + .attr(CombinedPledgeStabBoostAttr) + .attr(AddPledgeEffectAttr, ArenaTagType.GRASS_WATER_PLEDGE, Moves.WATER_PLEDGE) + .attr(AddPledgeEffectAttr, ArenaTagType.FIRE_GRASS_PLEDGE, Moves.FIRE_PLEDGE) + .attr(BypassRedirectAttr, true), new AttackMove(Moves.VOLT_SWITCH, Type.ELECTRIC, MoveCategory.SPECIAL, 70, 100, 20, -1, 0, 5) .attr(ForceSwitchOutAttr, true), new AttackMove(Moves.STRUGGLE_BUG, Type.BUG, MoveCategory.SPECIAL, 50, 100, 20, 100, 0, 5) @@ -8360,7 +8749,8 @@ export function initMoves() { .attr(CritOnlyAttr), new AttackMove(Moves.DRAGON_TAIL, Type.DRAGON, MoveCategory.PHYSICAL, 60, 90, 10, -1, -6, 5) .attr(ForceSwitchOutAttr) - .hidesTarget(), + .hidesTarget() + .partial(), // Should force random switches new SelfStatusMove(Moves.WORK_UP, Type.NORMAL, -1, 30, -1, 0, 5) .attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, true), new AttackMove(Moves.ELECTROWEB, Type.ELECTRIC, MoveCategory.SPECIAL, 55, 95, 15, 100, 0, 5) @@ -8436,11 +8826,11 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.SPATK ], 1, true) .danceMove(), new AttackMove(Moves.FREEZE_SHOCK, Type.ICE, MoveCategory.PHYSICAL, 140, 90, 5, 30, 0, 5) - .attr(ChargeAttr, ChargeAnim.FREEZE_SHOCK_CHARGING, i18next.t("moveTriggers:becameCloakedInFreezingLight", {pokemonName: "{USER}"})) + .attr(ChargeAttr, ChargeAnim.FREEZE_SHOCK_CHARGING, i18next.t("moveTriggers:becameCloakedInFreezingLight", { pokemonName: "{USER}" })) .attr(StatusEffectAttr, StatusEffect.PARALYSIS) .makesContact(false), new AttackMove(Moves.ICE_BURN, Type.ICE, MoveCategory.SPECIAL, 140, 90, 5, 30, 0, 5) - .attr(ChargeAttr, ChargeAnim.ICE_BURN_CHARGING, i18next.t("moveTriggers:becameCloakedInFreezingAir", {pokemonName: "{USER}"})) + .attr(ChargeAttr, ChargeAnim.ICE_BURN_CHARGING, i18next.t("moveTriggers:becameCloakedInFreezingAir", { pokemonName: "{USER}" })) .attr(StatusEffectAttr, StatusEffect.BURN) .ignoresVirtual(), new AttackMove(Moves.SNARL, Type.DARK, MoveCategory.SPECIAL, 55, 95, 15, 100, 0, 5) @@ -8474,7 +8864,7 @@ export function initMoves() { .target(MoveTarget.ALL) .condition((user, target, move) => { // If any fielded pokémon is grass-type and grounded. - return [...user.scene.getEnemyParty(), ...user.scene.getParty()].some((poke) => poke.isOfType(Type.GRASS) && poke.isGrounded()); + return [ ...user.scene.getEnemyParty(), ...user.scene.getParty() ].some((poke) => poke.isOfType(Type.GRASS) && poke.isGrounded()); }) .attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, false, (user, target, move) => target.isOfType(Type.GRASS) && target.isGrounded()), new StatusMove(Moves.STICKY_WEB, Type.BUG, -1, 20, -1, 0, 6) @@ -8483,25 +8873,25 @@ export function initMoves() { new AttackMove(Moves.FELL_STINGER, Type.BUG, MoveCategory.PHYSICAL, 50, 100, 25, -1, 0, 6) .attr(PostVictoryStatStageChangeAttr, [ Stat.ATK ], 3, true ), new AttackMove(Moves.PHANTOM_FORCE, Type.GHOST, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6) - .attr(ChargeAttr, ChargeAnim.PHANTOM_FORCE_CHARGING, i18next.t("moveTriggers:vanishedInstantly", {pokemonName: "{USER}"}), BattlerTagType.HIDDEN) + .attr(ChargeAttr, ChargeAnim.PHANTOM_FORCE_CHARGING, i18next.t("moveTriggers:vanishedInstantly", { pokemonName: "{USER}" }), BattlerTagType.HIDDEN) .ignoresProtect() .ignoresVirtual(), new StatusMove(Moves.TRICK_OR_TREAT, Type.GHOST, 100, 20, -1, 0, 6) .attr(AddTypeAttr, Type.GHOST) - .partial(), + .edgeCase(), // Weird interaction with Forest's Curse, reflect type, burn up new StatusMove(Moves.NOBLE_ROAR, Type.NORMAL, 100, 30, -1, 0, 6) .attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1) .soundBased(), new StatusMove(Moves.ION_DELUGE, Type.ELECTRIC, -1, 25, -1, 1, 6) - .target(MoveTarget.BOTH_SIDES) - .unimplemented(), + .attr(AddArenaTagAttr, ArenaTagType.ION_DELUGE) + .target(MoveTarget.BOTH_SIDES), new AttackMove(Moves.PARABOLIC_CHARGE, Type.ELECTRIC, MoveCategory.SPECIAL, 65, 100, 20, -1, 0, 6) .attr(HitHealAttr) .target(MoveTarget.ALL_NEAR_OTHERS) .triageMove(), new StatusMove(Moves.FORESTS_CURSE, Type.GRASS, 100, 20, -1, 0, 6) .attr(AddTypeAttr, Type.GRASS) - .partial(), + .edgeCase(), // Weird interaction with Trick or Treat, reflect type, burn up new AttackMove(Moves.PETAL_BLIZZARD, Type.GRASS, MoveCategory.PHYSICAL, 90, 100, 15, -1, 0, 6) .windMove() .makesContact(false) @@ -8509,7 +8899,7 @@ export function initMoves() { new AttackMove(Moves.FREEZE_DRY, Type.ICE, MoveCategory.SPECIAL, 70, 100, 20, 10, 0, 6) .attr(StatusEffectAttr, StatusEffect.FREEZE) .attr(WaterSuperEffectTypeMultiplierAttr) - .partial(), // This currently just multiplies the move's power instead of changing its effectiveness. It also doesn't account for abilities that modify type effectiveness such as tera shell. + .edgeCase(), // This currently just multiplies the move's power instead of changing its effectiveness. It also doesn't account for abilities that modify type effectiveness such as tera shell. new AttackMove(Moves.DISARMING_VOICE, Type.FAIRY, MoveCategory.SPECIAL, 40, -1, 15, -1, 0, 6) .soundBased() .target(MoveTarget.ALL_NEAR_ENEMIES), @@ -8537,7 +8927,7 @@ export function initMoves() { .attr(TerrainChangeAttr, TerrainType.MISTY) .target(MoveTarget.BOTH_SIDES), new StatusMove(Moves.ELECTRIFY, Type.ELECTRIC, -1, 20, -1, 0, 6) - .unimplemented(), + .attr(AddBattlerTagAttr, BattlerTagType.ELECTRIFIED, false, true), new AttackMove(Moves.PLAY_ROUGH, Type.FAIRY, MoveCategory.PHYSICAL, 90, 90, 10, 10, 0, 6) .attr(StatStageChangeAttr, [ Stat.ATK ], -1), new AttackMove(Moves.FAIRY_WIND, Type.FAIRY, MoveCategory.SPECIAL, 40, 100, 30, -1, 0, 6) @@ -8561,7 +8951,7 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.SPATK ], -1) .soundBased(), new AttackMove(Moves.DIAMOND_STORM, Type.ROCK, MoveCategory.PHYSICAL, 100, 95, 5, 50, 0, 6) - .attr(StatStageChangeAttr, [ Stat.DEF ], 2, true) + .attr(StatStageChangeAttr, [ Stat.DEF ], 2, true, undefined, undefined, undefined, undefined, true) .makesContact(false) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.STEAM_ERUPTION, Type.WATER, MoveCategory.SPECIAL, 110, 95, 5, 30, 0, 6) @@ -8594,14 +8984,14 @@ export function initMoves() { .powderMove() .unimplemented(), new SelfStatusMove(Moves.GEOMANCY, Type.FAIRY, -1, 10, -1, 0, 6) - .attr(ChargeAttr, ChargeAnim.GEOMANCY_CHARGING, i18next.t("moveTriggers:isChargingPower", {pokemonName: "{USER}"})) + .attr(ChargeAttr, ChargeAnim.GEOMANCY_CHARGING, i18next.t("moveTriggers:isChargingPower", { pokemonName: "{USER}" })) .attr(StatStageChangeAttr, [ Stat.SPATK, Stat.SPDEF, Stat.SPD ], 2, true) .ignoresVirtual(), new StatusMove(Moves.MAGNETIC_FLUX, Type.ELECTRIC, -1, 20, -1, 0, 6) - .attr(StatStageChangeAttr, [ Stat.DEF, Stat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => target.hasAbility(a, false))) + .attr(StatStageChangeAttr, [ Stat.DEF, Stat.SPDEF ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS ].find(a => target.hasAbility(a, false))) .ignoresSubstitute() .target(MoveTarget.USER_AND_ALLIES) - .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => p.hasAbility(a, false)))), + .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS ].find(a => p.hasAbility(a, false)))), new StatusMove(Moves.HAPPY_HOUR, Type.NORMAL, -1, 30, -1, 0, 6) // No animation .attr(AddArenaTagAttr, ArenaTagType.HAPPY_HOUR, null, true) .target(MoveTarget.USER_SIDE), @@ -8633,9 +9023,9 @@ export function initMoves() { .attr(NeutralDamageAgainstFlyingTypeMultiplierAttr) .attr(AddBattlerTagAttr, BattlerTagType.IGNORE_FLYING, false, false, 1, 1, true) .attr(HitsTagAttr, BattlerTagType.FLYING) - .attr(HitsTagAttr, BattlerTagType.MAGNET_RISEN) + .attr(HitsTagAttr, BattlerTagType.FLOATING) .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) - .attr(RemoveBattlerTagAttr, [BattlerTagType.FLYING, BattlerTagType.MAGNET_RISEN]) + .attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.FLOATING, BattlerTagType.TELEKINESIS ]) .makesContact(false) .target(MoveTarget.ALL_NEAR_ENEMIES), new AttackMove(Moves.THOUSAND_WAVES, Type.GROUND, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 6) @@ -8795,7 +9185,7 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.SPD ], -1, true) .punchingMove(), new StatusMove(Moves.FLORAL_HEALING, Type.FAIRY, -1, 10, -1, 0, 7) - .attr(BoostHealAttr, 0.5, 2/3, true, false, (user, target, move) => user.scene.arena.terrain?.terrainType === TerrainType.GRASSY) + .attr(BoostHealAttr, 0.5, 2 / 3, true, false, (user, target, move) => user.scene.arena.terrain?.terrainType === TerrainType.GRASSY) .triageMove(), new AttackMove(Moves.HIGH_HORSEPOWER, Type.GROUND, MoveCategory.PHYSICAL, 95, 95, 10, -1, 0, 7), new StatusMove(Moves.STRENGTH_SAP, Type.GRASS, 100, 10, -1, 0, 7) @@ -8804,7 +9194,7 @@ export function initMoves() { .condition((user, target, move) => target.getStatStage(Stat.ATK) > -6) .triageMove(), new AttackMove(Moves.SOLAR_BLADE, Type.GRASS, MoveCategory.PHYSICAL, 125, 100, 10, -1, 0, 7) - .attr(SunlightChargeAttr, ChargeAnim.SOLAR_BLADE_CHARGING, i18next.t("moveTriggers:isGlowing", {pokemonName: "{USER}"})) + .attr(SunlightChargeAttr, ChargeAnim.SOLAR_BLADE_CHARGING, i18next.t("moveTriggers:isGlowing", { pokemonName: "{USER}" })) .attr(AntiSunlightPowerDecreaseAttr) .slicingMove(), new AttackMove(Moves.LEAFAGE, Type.GRASS, MoveCategory.PHYSICAL, 40, 100, 40, -1, 0, 7) @@ -8817,10 +9207,10 @@ export function initMoves() { new SelfStatusMove(Moves.LASER_FOCUS, Type.NORMAL, -1, 30, -1, 0, 7) .attr(AddBattlerTagAttr, BattlerTagType.ALWAYS_CRIT, true, false), new StatusMove(Moves.GEAR_UP, Type.STEEL, -1, 20, -1, 0, 7) - .attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS].find(a => target.hasAbility(a, false))) + .attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], 1, false, (user, target, move) => !![ Abilities.PLUS, Abilities.MINUS ].find(a => target.hasAbility(a, false))) .ignoresSubstitute() .target(MoveTarget.USER_AND_ALLIES) - .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS].find(a => p.hasAbility(a, false)))), + .condition((user, target, move) => !![ user, user.getAlly() ].filter(p => p?.isActive()).find(p => !![ Abilities.PLUS, Abilities.MINUS ].find(a => p.hasAbility(a, false)))), new AttackMove(Moves.THROAT_CHOP, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 15, 100, 0, 7) .attr(AddBattlerTagAttr, BattlerTagType.THROAT_CHOPPED), new AttackMove(Moves.POLLEN_PUFF, Type.BUG, MoveCategory.SPECIAL, 90, 100, 15, -1, 0, 7) @@ -8846,7 +9236,7 @@ export function initMoves() { .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE) .attr(AddBattlerTagAttr, BattlerTagType.BURNED_UP, true, false) .attr(RemoveTypeAttr, Type.FIRE, (user) => { - user.scene.queueMessage(i18next.t("moveTriggers:burnedItselfOut", {pokemonName: getPokemonNameWithAffix(user)})); + user.scene.queueMessage(i18next.t("moveTriggers:burnedItselfOut", { pokemonName: getPokemonNameWithAffix(user) })); }), new StatusMove(Moves.SPEED_SWAP, Type.PSYCHIC, -1, 10, -1, 0, 7) .attr(SwapStatAttr, Stat.SPD) @@ -8887,15 +9277,15 @@ export function initMoves() { /* Unused */ new AttackMove(Moves.SINISTER_ARROW_RAID, Type.GHOST, MoveCategory.PHYSICAL, 180, -1, 1, -1, 0, 7) .makesContact(false) - .partial() + .edgeCase() // I assume it's because the user needs spirit shackle and decidueye .ignoresVirtual(), new AttackMove(Moves.MALICIOUS_MOONSAULT, Type.DARK, MoveCategory.PHYSICAL, 180, -1, 1, -1, 0, 7) .attr(AlwaysHitMinimizeAttr) .attr(HitsTagAttr, BattlerTagType.MINIMIZED, true) - .partial() + .edgeCase() // I assume it's because it needs darkest lariat and incineroar .ignoresVirtual(), new AttackMove(Moves.OCEANIC_OPERETTA, Type.WATER, MoveCategory.SPECIAL, 195, -1, 1, -1, 0, 7) - .partial() + .edgeCase() // I assume it's because it needs sparkling aria and primarina .ignoresVirtual(), new AttackMove(Moves.GUARDIAN_OF_ALOLA, Type.FAIRY, MoveCategory.SPECIAL, -1, -1, 1, -1, 0, 7) .unimplemented() @@ -8904,10 +9294,10 @@ export function initMoves() { .unimplemented() .ignoresVirtual(), new AttackMove(Moves.STOKED_SPARKSURFER, Type.ELECTRIC, MoveCategory.SPECIAL, 175, -1, 1, 100, 0, 7) - .partial() + .edgeCase() // I assume it's because it needs thunderbolt and Alola Raichu .ignoresVirtual(), new AttackMove(Moves.PULVERIZING_PANCAKE, Type.NORMAL, MoveCategory.PHYSICAL, 210, -1, 1, -1, 0, 7) - .partial() + .edgeCase() // I assume it's because it needs giga impact and snorlax .ignoresVirtual(), new SelfStatusMove(Moves.EXTREME_EVOBOOST, Type.NORMAL, -1, 1, -1, 0, 7) .attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 2, true) @@ -8938,13 +9328,13 @@ export function initMoves() { .attr(RechargeAttr), new AttackMove(Moves.SPECTRAL_THIEF, Type.GHOST, MoveCategory.PHYSICAL, 90, 100, 10, -1, 0, 7) .ignoresSubstitute() - .partial(), + .partial(), // Does not steal stats new AttackMove(Moves.SUNSTEEL_STRIKE, Type.STEEL, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 7) .ignoresAbilities() - .partial(), + .edgeCase(), // Should not ignore abilities when called virtually (metronome) new AttackMove(Moves.MOONGEIST_BEAM, Type.GHOST, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7) .ignoresAbilities() - .partial(), + .edgeCase(), // Should not ignore abilities when called virtually (metronome) new StatusMove(Moves.TEARFUL_LOOK, Type.NORMAL, -1, 20, -1, 0, 7) .attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPATK ], -1), new AttackMove(Moves.ZING_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 80, 100, 10, 30, 0, 7) @@ -8955,7 +9345,7 @@ export function initMoves() { .attr(FormChangeItemTypeAttr), /* Unused */ new AttackMove(Moves.TEN_MILLION_VOLT_THUNDERBOLT, Type.ELECTRIC, MoveCategory.SPECIAL, 195, -1, 1, -1, 0, 7) - .partial() + .edgeCase() // I assume it's because it needs thunderbolt and pikachu in a cap .ignoresVirtual(), /* End Unused */ new AttackMove(Moves.MIND_BLOWN, Type.FIRE, MoveCategory.SPECIAL, 150, 100, 5, -1, 0, 7) @@ -8963,12 +9353,12 @@ export function initMoves() { .attr(HalfSacrificialAttr) .target(MoveTarget.ALL_NEAR_OTHERS), new AttackMove(Moves.PLASMA_FISTS, Type.ELECTRIC, MoveCategory.PHYSICAL, 100, 100, 15, -1, 0, 7) - .attr(AddArenaTagAttr, ArenaTagType.PLASMA_FISTS, 1) + .attr(AddArenaTagAttr, ArenaTagType.ION_DELUGE, 1) .punchingMove(), new AttackMove(Moves.PHOTON_GEYSER, Type.PSYCHIC, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 7) .attr(PhotonGeyserCategoryAttr) .ignoresAbilities() - .partial(), + .edgeCase(), // Should not ignore abilities when called virtually (metronome) /* Unused */ new AttackMove(Moves.LIGHT_THAT_BURNS_THE_SKY, Type.PSYCHIC, MoveCategory.SPECIAL, 200, -1, 1, -1, 0, 7) .attr(PhotonGeyserCategoryAttr) @@ -8981,17 +9371,17 @@ export function initMoves() { .ignoresAbilities() .ignoresVirtual(), new AttackMove(Moves.LETS_SNUGGLE_FOREVER, Type.FAIRY, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7) - .partial() + .edgeCase() // I assume it needs play rough and mimikyu .ignoresVirtual(), new AttackMove(Moves.SPLINTERED_STORMSHARDS, Type.ROCK, MoveCategory.PHYSICAL, 190, -1, 1, -1, 0, 7) .attr(ClearTerrainAttr) .makesContact(false) .ignoresVirtual(), new AttackMove(Moves.CLANGOROUS_SOULBLAZE, Type.DRAGON, MoveCategory.SPECIAL, 185, -1, 1, 100, 0, 7) - .attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true) + .attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true, undefined, undefined, undefined, undefined, true) .soundBased() .target(MoveTarget.ALL_NEAR_ENEMIES) - .partial() + .edgeCase() // I assume it needs clanging scales and Kommo-O .ignoresVirtual(), /* End Unused */ new AttackMove(Moves.ZIPPY_ZAP, Type.ELECTRIC, MoveCategory.PHYSICAL, 50, 100, 15, -1, 2, 7) //LGPE Implementation @@ -9054,14 +9444,14 @@ export function initMoves() { new AttackMove(Moves.JAW_LOCK, Type.DARK, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 8) .attr(JawLockAttr) .bitingMove(), - new SelfStatusMove(Moves.STUFF_CHEEKS, Type.NORMAL, -1, 10, -1, 0, 8) // TODO: Stuff Cheeks should not be selectable when the user does not have a berry, see wiki + new SelfStatusMove(Moves.STUFF_CHEEKS, Type.NORMAL, -1, 10, -1, 0, 8) .attr(EatBerryAttr) .attr(StatStageChangeAttr, [ Stat.DEF ], 2, true) .condition((user) => { const userBerries = user.scene.findModifiers(m => m instanceof BerryModifier, user.isPlayer()); return userBerries.length > 0; }) - .partial(), + .edgeCase(), // Stuff Cheeks should not be selectable when the user does not have a berry, see wiki new SelfStatusMove(Moves.NO_RETREAT, Type.FIGHTING, -1, 5, -1, 0, 8) .attr(StatStageChangeAttr, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ], 1, true) .attr(AddBattlerTagAttr, BattlerTagType.NO_RETREAT, true, false) @@ -9075,7 +9465,7 @@ export function initMoves() { new AttackMove(Moves.DRAGON_DARTS, Type.DRAGON, MoveCategory.PHYSICAL, 50, 100, 10, -1, 0, 8) .attr(MultiHitAttr, MultiHitType._2) .makesContact(false) - .partial(), + .partial(), // smart targetting is unimplemented new StatusMove(Moves.TEATIME, Type.NORMAL, -1, 10, -1, 0, 8) .attr(EatBerryAttr) .target(MoveTarget.ALL), @@ -9087,7 +9477,7 @@ export function initMoves() { .attr(FirstAttackDoublePowerAttr) .bitingMove(), new StatusMove(Moves.COURT_CHANGE, Type.NORMAL, 100, 10, -1, 0, 8) - .attr(SwapArenaTagsAttr, [ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.MIST, ArenaTagType.REFLECT, ArenaTagType.SPIKES, ArenaTagType.STEALTH_ROCK, ArenaTagType.STICKY_WEB, ArenaTagType.TAILWIND, ArenaTagType.TOXIC_SPIKES]), + .attr(SwapArenaTagsAttr, [ ArenaTagType.AURORA_VEIL, ArenaTagType.LIGHT_SCREEN, ArenaTagType.MIST, ArenaTagType.REFLECT, ArenaTagType.SPIKES, ArenaTagType.STEALTH_ROCK, ArenaTagType.STICKY_WEB, ArenaTagType.TAILWIND, ArenaTagType.TOXIC_SPIKES ]), new AttackMove(Moves.MAX_FLARE, Type.FIRE, MoveCategory.PHYSICAL, 10, -1, 10, -1, 0, 8) .target(MoveTarget.NEAR_ENEMY) .unimplemented() @@ -9226,12 +9616,12 @@ export function initMoves() { .attr(ClearTerrainAttr) .condition((user, target, move) => !!user.scene.arena.terrain), new AttackMove(Moves.SCALE_SHOT, Type.DRAGON, MoveCategory.PHYSICAL, 25, 90, 20, -1, 0, 8) - .attr(StatStageChangeAttr, [Stat.SPD], 1, true, null, true, false, MoveEffectTrigger.HIT, false, true) - .attr(StatStageChangeAttr, [Stat.DEF], -1, true, null, true, false, MoveEffectTrigger.HIT, false, true) + .attr(StatStageChangeAttr, [ Stat.SPD ], 1, true, null, true, false, MoveEffectTrigger.HIT, false, true) + .attr(StatStageChangeAttr, [ Stat.DEF ], -1, true, null, true, false, MoveEffectTrigger.HIT, false, true) .attr(MultiHitAttr) .makesContact(false), new AttackMove(Moves.METEOR_BEAM, Type.ROCK, MoveCategory.SPECIAL, 120, 90, 10, 100, 0, 8) - .attr(ChargeAttr, ChargeAnim.METEOR_BEAM_CHARGING, i18next.t("moveTriggers:isOverflowingWithSpacePower", {pokemonName: "{USER}"}), null, true) + .attr(ChargeAttr, ChargeAnim.METEOR_BEAM_CHARGING, i18next.t("moveTriggers:isOverflowingWithSpacePower", { pokemonName: "{USER}" }), null, true) .attr(StatStageChangeAttr, [ Stat.SPATK ], 1, true) .ignoresVirtual(), new AttackMove(Moves.SHELL_SIDE_ARM, Type.POISON, MoveCategory.SPECIAL, 90, 100, 10, 20, 0, 8) @@ -9312,7 +9702,7 @@ export function initMoves() { .attr(AttackReducePpMoveAttr, 3) .soundBased(), new AttackMove(Moves.DIRE_CLAW, Type.POISON, MoveCategory.PHYSICAL, 80, 100, 15, 50, 0, 8) - .attr(MultiStatusEffectAttr, [StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP]), + .attr(MultiStatusEffectAttr, [ StatusEffect.POISON, StatusEffect.PARALYSIS, StatusEffect.SLEEP ]), new AttackMove(Moves.PSYSHIELD_BASH, Type.PSYCHIC, MoveCategory.PHYSICAL, 70, 90, 10, 100, 0, 8) .attr(StatStageChangeAttr, [ Stat.DEF ], 1, true), new SelfStatusMove(Moves.POWER_SHIFT, Type.NORMAL, -1, 10, -1, 0, 8) @@ -9361,9 +9751,8 @@ export function initMoves() { new AttackMove(Moves.TRIPLE_ARROWS, Type.FIGHTING, MoveCategory.PHYSICAL, 90, 100, 10, 30, 0, 8) .makesContact(false) .attr(HighCritAttr) - .attr(StatStageChangeAttr, [ Stat.DEF ], -1) - .attr(FlinchAttr) - .partial(), + .attr(StatStageChangeAttr, [ Stat.DEF ], -1, undefined, undefined, undefined, undefined, undefined, undefined, undefined, 50) + .attr(FlinchAttr), new AttackMove(Moves.INFERNAL_PARADE, Type.GHOST, MoveCategory.SPECIAL, 60, 100, 15, 30, 0, 8) .attr(StatusEffectAttr, StatusEffect.BURN) .attr(MovePowerMultiplierAttr, (user, target, move) => target.status ? 2 : 1), @@ -9515,7 +9904,7 @@ export function initMoves() { .attr(StatStageChangeAttr, [ Stat.SPDEF ], -2), new AttackMove(Moves.ORDER_UP, Type.DRAGON, MoveCategory.PHYSICAL, 80, 100, 10, 100, 0, 9) .makesContact(false) - .partial(), + .partial(), // No effect implemented (requires Commander) new AttackMove(Moves.JET_PUNCH, Type.WATER, MoveCategory.PHYSICAL, 60, 100, 15, -1, 1, 9) .punchingMove(), new StatusMove(Moves.SPICY_EXTRACT, Type.GRASS, -1, 15, -1, 0, 9) @@ -9588,19 +9977,19 @@ export function initMoves() { .slicingMove(), new AttackMove(Moves.HYDRO_STEAM, Type.WATER, MoveCategory.SPECIAL, 80, 100, 15, -1, 0, 9) .attr(IgnoreWeatherTypeDebuffAttr, WeatherType.SUNNY) - .attr(MovePowerMultiplierAttr, (user, target, move) => [WeatherType.SUNNY, WeatherType.HARSH_SUN].includes(user.scene.arena.weather?.weatherType!) && !user.scene.arena.weather?.isEffectSuppressed(user.scene) ? 1.5 : 1), // TODO: is this bang correct? + .attr(MovePowerMultiplierAttr, (user, target, move) => [ WeatherType.SUNNY, WeatherType.HARSH_SUN ].includes(user.scene.arena.weather?.weatherType!) && !user.scene.arena.weather?.isEffectSuppressed(user.scene) ? 1.5 : 1), // TODO: is this bang correct? new AttackMove(Moves.RUINATION, Type.DARK, MoveCategory.SPECIAL, -1, 90, 10, -1, 0, 9) .attr(TargetHalfHpDamageAttr), new AttackMove(Moves.COLLISION_COURSE, Type.FIGHTING, MoveCategory.PHYSICAL, 100, 100, 5, -1, 0, 9) - .attr(MovePowerMultiplierAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2 ? 5461/4096 : 1), + .attr(MovePowerMultiplierAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2 ? 5461 / 4096 : 1), new AttackMove(Moves.ELECTRO_DRIFT, Type.ELECTRIC, MoveCategory.SPECIAL, 100, 100, 5, -1, 0, 9) - .attr(MovePowerMultiplierAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2 ? 5461/4096 : 1) + .attr(MovePowerMultiplierAttr, (user, target, move) => target.getAttackTypeEffectiveness(move.type, user) >= 2 ? 5461 / 4096 : 1) .makesContact(), new SelfStatusMove(Moves.SHED_TAIL, Type.NORMAL, -1, 10, -1, 0, 9) .attr(AddSubstituteAttr, 0.5) .attr(ForceSwitchOutAttr, true, SwitchType.SHED_TAIL), new SelfStatusMove(Moves.CHILLY_RECEPTION, Type.ICE, -1, 10, -1, 0, 9) - .attr(PreMoveMessageAttr, (user, move) => i18next.t("moveTriggers:chillyReception", {pokemonName: getPokemonNameWithAffix(user)})) + .attr(PreMoveMessageAttr, (user, move) => i18next.t("moveTriggers:chillyReception", { pokemonName: getPokemonNameWithAffix(user) })) .attr(ChillyReceptionAttr, true), new SelfStatusMove(Moves.TIDY_UP, Type.NORMAL, -1, 10, -1, 0, 9) .attr(StatStageChangeAttr, [ Stat.ATK, Stat.SPD ], 1, true, null, true, true) @@ -9635,7 +10024,7 @@ export function initMoves() { }) .attr(AddBattlerTagAttr, BattlerTagType.DOUBLE_SHOCKED, true, false) .attr(RemoveTypeAttr, Type.ELECTRIC, (user) => { - user.scene.queueMessage(i18next.t("moveTriggers:usedUpAllElectricity", {pokemonName: getPokemonNameWithAffix(user)})); + user.scene.queueMessage(i18next.t("moveTriggers:usedUpAllElectricity", { pokemonName: getPokemonNameWithAffix(user) })); }), new AttackMove(Moves.GIGATON_HAMMER, Type.STEEL, MoveCategory.PHYSICAL, 160, 100, 5, -1, 0, 9) .makesContact(false) @@ -9727,8 +10116,7 @@ export function initMoves() { new AttackMove(Moves.UPPER_HAND, Type.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, 100, 3, 9) .attr(FlinchAttr) .condition((user, target, move) => user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.command === Command.FIGHT && !target.turnData.acted && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].category !== MoveCategory.STATUS && allMoves[user.scene.currentBattle.turnCommands[target.getBattlerIndex()]?.move?.move!].priority > 0 ) // TODO: is this bang correct? - //TODO: Should also apply when target move priority increased by ability ex. gale wings - .partial(), + .partial(), // Should also apply when target move priority increased by ability ex. gale wings new AttackMove(Moves.MALIGNANT_CHAIN, Type.POISON, MoveCategory.SPECIAL, 100, 100, 5, 50, 0, 9) .attr(StatusEffectAttr, StatusEffect.TOXIC) ); diff --git a/src/data/mystery-encounters/encounters/a-trainers-test-encounter.ts b/src/data/mystery-encounters/encounters/a-trainers-test-encounter.ts index 7c2d7052ff9..f0155b4f2a4 100644 --- a/src/data/mystery-encounters/encounters/a-trainers-test-encounter.ts +++ b/src/data/mystery-encounters/encounters/a-trainers-test-encounter.ts @@ -44,32 +44,32 @@ export const ATrainersTestEncounter: MysteryEncounter = let spriteKeys; let trainerNameKey: string; switch (randSeedInt(5)) { - default: - case 0: - trainerType = TrainerType.BUCK; - spriteKeys = getSpriteKeysFromSpecies(Species.CLAYDOL); - trainerNameKey = "buck"; - break; - case 1: - trainerType = TrainerType.CHERYL; - spriteKeys = getSpriteKeysFromSpecies(Species.BLISSEY); - trainerNameKey = "cheryl"; - break; - case 2: - trainerType = TrainerType.MARLEY; - spriteKeys = getSpriteKeysFromSpecies(Species.ARCANINE); - trainerNameKey = "marley"; - break; - case 3: - trainerType = TrainerType.MIRA; - spriteKeys = getSpriteKeysFromSpecies(Species.ALAKAZAM, false, 1); - trainerNameKey = "mira"; - break; - case 4: - trainerType = TrainerType.RILEY; - spriteKeys = getSpriteKeysFromSpecies(Species.LUCARIO, false, 1); - trainerNameKey = "riley"; - break; + default: + case 0: + trainerType = TrainerType.BUCK; + spriteKeys = getSpriteKeysFromSpecies(Species.CLAYDOL); + trainerNameKey = "buck"; + break; + case 1: + trainerType = TrainerType.CHERYL; + spriteKeys = getSpriteKeysFromSpecies(Species.BLISSEY); + trainerNameKey = "cheryl"; + break; + case 2: + trainerType = TrainerType.MARLEY; + spriteKeys = getSpriteKeysFromSpecies(Species.ARCANINE); + trainerNameKey = "marley"; + break; + case 3: + trainerType = TrainerType.MIRA; + spriteKeys = getSpriteKeysFromSpecies(Species.ALAKAZAM, false, 1); + trainerNameKey = "mira"; + break; + case 4: + trainerType = TrainerType.RILEY; + spriteKeys = getSpriteKeysFromSpecies(Species.LUCARIO, false, 1); + trainerNameKey = "riley"; + break; } // Dialogue and tokens for trainer @@ -128,6 +128,7 @@ export const ATrainersTestEncounter: MysteryEncounter = return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -149,11 +150,11 @@ export const ATrainersTestEncounter: MysteryEncounter = pulled: false, sourceType: EggSourceType.EVENT, eggDescriptor: encounter.misc.trainerEggDescription, - tier: EggTier.ULTRA + tier: EggTier.EPIC }; encounter.setDialogueToken("eggType", i18next.t(`${namespace}:eggTypes.epic`)); - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SACRED_ASH], guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA], fillRemaining: true }, [eggOptions]); - return initBattleWithEnemyConfig(scene, config); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.SACRED_ASH ], guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ULTRA ], fillRemaining: true }, [ eggOptions ]); + await initBattleWithEnemyConfig(scene, config); } ) .withSimpleOption( @@ -171,10 +172,10 @@ export const ATrainersTestEncounter: MysteryEncounter = pulled: false, sourceType: EggSourceType.EVENT, eggDescriptor: encounter.misc.trainerEggDescription, - tier: EggTier.GREAT + tier: EggTier.RARE }; encounter.setDialogueToken("eggType", i18next.t(`${namespace}:eggTypes.rare`)); - setEncounterRewards(scene, { fillRemaining: false, rerollMultiplier: -1 }, [eggOptions]); + setEncounterRewards(scene, { fillRemaining: false, rerollMultiplier: -1 }, [ eggOptions ]); leaveEncounterWithoutBattle(scene); } ) diff --git a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts index 0b32f857d75..c53b802bb22 100644 --- a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts +++ b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts @@ -166,6 +166,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = text: `${namespace}:intro`, } ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -195,7 +196,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = // Can't define stack count on a ModifierType, have to just create separate instances for each stack // Overflow berries will be "lost" on the boss, but it's un-catchable anyway for (let i = 0; i < berryMod.stackCount; i++) { - const modifierType = generateModifierType(scene, modifierTypes.BERRY, [berryMod.berryType]) as PokemonHeldItemModifierType; + const modifierType = generateModifierType(scene, modifierTypes.BERRY, [ berryMod.berryType ]) as PokemonHeldItemModifierType; bossModifierConfigs.push({ modifier: modifierType }); } }); @@ -204,8 +205,8 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = // SpDef buff below wave 50, +1 to all stats otherwise const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ? - [Stat.SPDEF] : - [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD]; + [ Stat.SPDEF ] : + [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ]; // Calculate boss mon const config: EnemyPartyConfig = { @@ -215,9 +216,9 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = species: getPokemonSpecies(Species.GREEDENT), isBoss: true, bossSegments: 3, - moveSet: [Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH], + moveSet: [ Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH ], modifierConfigs: bossModifierConfigs, - tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { queueEncounterMessage(pokemon.scene, `${namespace}:option.1.boss_enraged`); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1)); @@ -226,7 +227,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = ], }; - encounter.enemyPartyConfigs = [config]; + encounter.enemyPartyConfigs = [ config ]; encounter.setDialogueToken("greedentName", getPokemonSpecies(Species.GREEDENT).getName()); return true; @@ -280,12 +281,12 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = setEncounterRewards(scene, { fillRemaining: true }, undefined, givePartyPokemonReviverSeeds); encounter.startOfBattleEffects.push({ sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.ENEMY], + targets: [ BattlerIndex.ENEMY ], move: new PokemonMove(Moves.STUFF_CHEEKS), ignorePp: true }); - transitionMysteryEncounterIntroVisuals(scene, true, true, 500); + await transitionMysteryEncounterIntroVisuals(scene, true, true, 500); await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]); }) .build() @@ -320,14 +321,14 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = Phaser.Math.RND.shuffle(berryTypesAsArray); const randBerryType = berryTypesAsArray.pop(); - const berryModType = generateModifierType(scene, modifierTypes.BERRY, [randBerryType]) as BerryModifierType; + const berryModType = generateModifierType(scene, modifierTypes.BERRY, [ randBerryType ]) as BerryModifierType; applyModifierTypeToPlayerPokemon(scene, pokemon, berryModType); } } }); await scene.updateModifiers(true); - transitionMysteryEncounterIntroVisuals(scene, true, true, 500); + await transitionMysteryEncounterIntroVisuals(scene, true, true, 500); leaveEncounterWithoutBattle(scene, true); }) .build() @@ -355,10 +356,10 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = // Greedent joins the team, level equal to 2 below highest party member const level = getHighestLevelPlayerPokemon(scene, false, true).level - 2; const greedent = new EnemyPokemon(scene, getPokemonSpecies(Species.GREEDENT), level, TrainerSlot.NONE, false); - greedent.moveset = [new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF)]; + greedent.moveset = [ new PokemonMove(Moves.THRASH), new PokemonMove(Moves.BODY_PRESS), new PokemonMove(Moves.STUFF_CHEEKS), new PokemonMove(Moves.SLACK_OFF) ]; greedent.passive = true; - transitionMysteryEncounterIntroVisuals(scene, true, true, 500); + await transitionMysteryEncounterIntroVisuals(scene, true, true, 500); await catchPokemon(scene, greedent, null, PokeballType.POKEBALL, false); leaveEncounterWithoutBattle(scene, true); }) @@ -472,7 +473,7 @@ function doGreedentEatBerries(scene: BattleScene) { */ function doBerrySpritePile(scene: BattleScene, isEat: boolean = false) { const berryAddDelay = 150; - let animationOrder = ["starf", "sitrus", "lansat", "salac", "apicot", "enigma", "liechi", "ganlon", "lum", "petaya", "leppa"]; + let animationOrder = [ "starf", "sitrus", "lansat", "salac", "apicot", "enigma", "liechi", "ganlon", "lum", "petaya", "leppa" ]; if (isEat) { animationOrder = animationOrder.reverse(); } @@ -496,7 +497,7 @@ function doBerrySpritePile(scene: BattleScene, isEat: boolean = false) { // Animate Petaya berry falling off the pile if (berry === "petaya" && sprite && tintSprite && !isEat) { scene.time.delayedCall(200, () => { - doBerryBounce(scene, [sprite, tintSprite], 30, 500); + doBerryBounce(scene, [ sprite, tintSprite ], 30, 500); }); } }); diff --git a/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts b/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts index ceb33ee2b8f..ec0fa12c7e1 100644 --- a/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts +++ b/src/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter.ts @@ -65,6 +65,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = speaker: `${namespace}:speaker`, }, ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) diff --git a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts index 55c66642944..095f8a8473b 100644 --- a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts +++ b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts @@ -69,7 +69,7 @@ export const BerriesAboundEncounter: MysteryEncounter = isBoss: true }], }; - encounter.enemyPartyConfigs = [config]; + encounter.enemyPartyConfigs = [ config ]; // Calculate the number of extra berries that player receives // 10-40: 2, 40-120: 4, 120-160: 5, 160-180: 7 @@ -110,6 +110,7 @@ export const BerriesAboundEncounter: MysteryEncounter = return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -193,11 +194,11 @@ export const BerriesAboundEncounter: MysteryEncounter = // Defense/Spd buffs below wave 50, +1 to all stats otherwise const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ? - [Stat.DEF, Stat.SPDEF, Stat.SPD] : - [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD]; + [ Stat.DEF, Stat.SPDEF, Stat.SPD ] : + [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ]; const config = scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]; - config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON]; + config.pokemonConfigs![0].tags = [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ]; config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => { queueEncounterMessage(pokemon.scene, `${namespace}:option.2.boss_enraged`); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1)); @@ -208,7 +209,7 @@ export const BerriesAboundEncounter: MysteryEncounter = return; } else { // Gains 1 berry for every 10% faster the player's pokemon is than the enemy, up to a max of numBerries, minimum of 2 - const numBerriesGrabbed = Math.max(Math.min(Math.round((speedDiff - 1)/0.08), numBerries), 2); + const numBerriesGrabbed = Math.max(Math.min(Math.round((speedDiff - 1) / 0.08), numBerries), 2); encounter.setDialogueToken("numBerries", String(numBerriesGrabbed)); const doFasterBerryRewards = () => { const berryText = i18next.t(`${namespace}:berries`); @@ -250,7 +251,7 @@ export const BerriesAboundEncounter: MysteryEncounter = function tryGiveBerry(scene: BattleScene, prioritizedPokemon?: PlayerPokemon) { const berryType = randSeedInt(Object.keys(BerryType).filter(s => !isNaN(Number(s))).length) as BerryType; - const berry = generateModifierType(scene, modifierTypes.BERRY, [berryType]) as BerryModifierType; + const berry = generateModifierType(scene, modifierTypes.BERRY, [ berryType ]) as BerryModifierType; const party = scene.getParty(); diff --git a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts index 6847ab8b832..b5d47cf6912 100644 --- a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts +++ b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts @@ -181,7 +181,7 @@ const MISC_TUTOR_MOVES = [ /** * Wave breakpoints that determine how strong to make the Bug-Type Superfan's team */ -const WAVE_LEVEL_BREAKPOINTS = [30, 50, 70, 100, 120, 140, 160]; +const WAVE_LEVEL_BREAKPOINTS = [ 30, 50, 70, 100, 120, 140, 160 ]; /** * Bug Type Superfan encounter. @@ -193,7 +193,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = .withEncounterTier(MysteryEncounterTier.GREAT) .withPrimaryPokemonRequirement(new CombinationPokemonRequirement( // Must have at least 1 Bug type on team, OR have a bug item somewhere on the team - new HeldItemRequirement(["BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier"], 1), + new HeldItemRequirement([ "BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier" ], 1), new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1), new TypeRequirement(Type.BUG, false, 1) )) @@ -268,7 +268,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = const requiredItems = [ generateModifierType(scene, modifierTypes.QUICK_CLAW), generateModifierType(scene, modifierTypes.GRIP_CLAW), - generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.BUG]), + generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.BUG ]), ]; const requiredItemString = requiredItems.map(m => m?.name ?? "unknown").join("/"); @@ -276,6 +276,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -331,7 +332,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = encounter.setDialogueToken("numBugTypes", numBugTypesText); if (numBugTypes < 2) { - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SUPER_LURE, modifierTypes.GREAT_BALL], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.SUPER_LURE, modifierTypes.GREAT_BALL ], fillRemaining: false }); encounter.selectedOption!.dialogue!.selected = [ { speaker: `${namespace}:speaker`, @@ -339,7 +340,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = }, ]; } else if (numBugTypes < 4) { - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.QUICK_CLAW, modifierTypes.MAX_LURE, modifierTypes.ULTRA_BALL], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.QUICK_CLAW, modifierTypes.MAX_LURE, modifierTypes.ULTRA_BALL ], fillRemaining: false }); encounter.selectedOption!.dialogue!.selected = [ { speaker: `${namespace}:speaker`, @@ -347,7 +348,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = }, ]; } else if (numBugTypes < 6) { - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.GRIP_CLAW, modifierTypes.MAX_LURE, modifierTypes.ROGUE_BALL], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.GRIP_CLAW, modifierTypes.MAX_LURE, modifierTypes.ROGUE_BALL ], fillRemaining: false }); encounter.selectedOption!.dialogue!.selected = [ { speaker: `${namespace}:speaker`, @@ -356,7 +357,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = ]; } else { // If player has any evolution/form change items that are valid for their party, will spawn one of those items in addition to a Master Ball - const modifierOptions: ModifierTypeOption[] = [generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)!]; + const modifierOptions: ModifierTypeOption[] = [ generateModifierTypeOption(scene, modifierTypes.MASTER_BALL)!, generateModifierTypeOption(scene, modifierTypes.MAX_LURE)! ]; const specialOptions: ModifierTypeOption[] = []; const nonRareEvolutionModifier = generateModifierTypeOption(scene, modifierTypes.EVOLUTION_ITEM); @@ -397,7 +398,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = .newOptionWithMode(MysteryEncounterOptionMode.DISABLED_OR_DEFAULT) .withPrimaryPokemonRequirement(new CombinationPokemonRequirement( // Meets one or both of the below reqs - new HeldItemRequirement(["BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier"], 1), + new HeldItemRequirement([ "BypassSpeedChanceModifier", "ContactHeldItemTransferChanceModifier" ], 1), new AttackTypeBoosterHeldItemTypeRequirement(Type.BUG, 1) )) .withDialogue({ @@ -474,7 +475,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = const bugNet = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_GOLDEN_BUG_NET)!; bugNet.type.tier = ModifierTier.ROGUE; - setEncounterRewards(scene, { guaranteedModifierTypeOptions: [bugNet], guaranteedModifierTypeFuncs: [modifierTypes.REVIVER_SEED], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ bugNet ], guaranteedModifierTypeFuncs: [ modifierTypes.REVIVER_SEED ], fillRemaining: false }); leaveEncounterWithoutBattle(scene, true); }) .build()) @@ -535,7 +536,7 @@ function getTrainerConfigForWave(waveIndex: number) { })) .setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true)) .setPartyMemberFunc(3, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true)) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => { if (!isNullOrUndefined(pool3Mon.formIndex)) { p.formIndex = pool3Mon.formIndex; p.generateAndPopulateMoveset(); @@ -558,14 +559,14 @@ function getTrainerConfigForWave(waveIndex: number) { p.generateName(); })) .setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true)) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => { if (!isNullOrUndefined(pool3Mon.formIndex)) { p.formIndex = pool3Mon.formIndex; p.generateAndPopulateMoveset(); p.generateName(); } })) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([pool3Mon2.species], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ pool3Mon2.species ], TrainerSlot.TRAINER, true, p => { if (!isNullOrUndefined(pool3Mon2.formIndex)) { p.formIndex = pool3Mon2.formIndex; p.generateAndPopulateMoveset(); @@ -586,7 +587,7 @@ function getTrainerConfigForWave(waveIndex: number) { p.generateName(); })) .setPartyMemberFunc(2, getRandomPartyMemberFunc(POOL_2_POKEMON, TrainerSlot.TRAINER, true)) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => { if (!isNullOrUndefined(pool3Mon.formIndex)) { p.formIndex = pool3Mon.formIndex; p.generateAndPopulateMoveset(); @@ -611,14 +612,14 @@ function getTrainerConfigForWave(waveIndex: number) { p.generateAndPopulateMoveset(); p.generateName(); })) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([pool3Mon.species], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ pool3Mon.species ], TrainerSlot.TRAINER, true, p => { if (!isNullOrUndefined(pool3Mon.formIndex)) { p.formIndex = pool3Mon.formIndex; p.generateAndPopulateMoveset(); p.generateName(); } })) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([pool3Mon2.species], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ pool3Mon2.species ], TrainerSlot.TRAINER, true, p => { if (!isNullOrUndefined(pool3Mon2.formIndex)) { p.formIndex = pool3Mon2.formIndex; p.generateAndPopulateMoveset(); diff --git a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts index 79f29662ef0..33d0127ff5b 100644 --- a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts +++ b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts @@ -129,25 +129,26 @@ export const ClowningAroundEncounter: MysteryEncounter = { species: getPokemonSpecies(Species.MR_MIME), isBoss: true, - moveSet: [Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC] + moveSet: [ Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC ] }, { // Blacephalon has the random ability from pool, and 2 entirely random types to fit with the theme of the encounter species: getPokemonSpecies(Species.BLACEPHALON), - mysteryEncounterPokemonData: new CustomPokemonData({ ability: ability, types: [randSeedInt(18), randSeedInt(18)] }), + mysteryEncounterPokemonData: new CustomPokemonData({ ability: ability, types: [ randSeedInt(18), randSeedInt(18) ] }), isBoss: true, - moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN] + moveSet: [ Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN ] }, ], doubleBattle: true }); // Load animations/sfx for start of fight moves - loadCustomMovesForEncounter(scene, [Moves.ROLE_PLAY, Moves.TAUNT]); + loadCustomMovesForEncounter(scene, [ Moves.ROLE_PLAY, Moves.TAUNT ]); encounter.setDialogueToken("blacephalonName", getPokemonSpecies(Species.BLACEPHALON).getName()); return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -175,19 +176,19 @@ export const ClowningAroundEncounter: MysteryEncounter = encounter.startOfBattleEffects.push( { // Mr. Mime copies the Blacephalon's random ability sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.ENEMY_2], + targets: [ BattlerIndex.ENEMY_2 ], move: new PokemonMove(Moves.ROLE_PLAY), ignorePp: true }, { sourceBattlerIndex: BattlerIndex.ENEMY_2, - targets: [BattlerIndex.PLAYER], + targets: [ BattlerIndex.PLAYER ], move: new PokemonMove(Moves.TAUNT), ignorePp: true }, { sourceBattlerIndex: BattlerIndex.ENEMY_2, - targets: [BattlerIndex.PLAYER_2], + targets: [ BattlerIndex.PLAYER_2 ], move: new PokemonMove(Moves.TAUNT), ignorePp: true }); @@ -336,11 +337,11 @@ export const ClowningAroundEncounter: MysteryEncounter = .filter(move => move && !originalTypes.includes(move.getMove().type) && move.getMove().category !== MoveCategory.STATUS) .map(move => move!.getMove().type); if (priorityTypes?.length > 0) { - priorityTypes = [...new Set(priorityTypes)].sort(); + priorityTypes = [ ...new Set(priorityTypes) ].sort(); priorityTypes = randSeedShuffle(priorityTypes); } - const newTypes = [originalTypes[0]]; + const newTypes = [ originalTypes[0] ]; let secondType: Type | null = null; while (secondType === null || secondType === newTypes[0] || originalTypes.includes(secondType)) { if (priorityTypes.length > 0) { @@ -444,37 +445,37 @@ function generateItemsOfTier(scene: BattleScene, pokemon: PlayerPokemon, numItem // Pools have instances of the modifier type equal to the max stacks that modifier can be applied to any one pokemon // This is to prevent "over-generating" a random item of a certain type during item swaps const ultraPool = [ - [modifierTypes.REVIVER_SEED, 1], - [modifierTypes.GOLDEN_PUNCH, 5], - [modifierTypes.ATTACK_TYPE_BOOSTER, 99], - [modifierTypes.QUICK_CLAW, 3], - [modifierTypes.WIDE_LENS, 3] + [ modifierTypes.REVIVER_SEED, 1 ], + [ modifierTypes.GOLDEN_PUNCH, 5 ], + [ modifierTypes.ATTACK_TYPE_BOOSTER, 99 ], + [ modifierTypes.QUICK_CLAW, 3 ], + [ modifierTypes.WIDE_LENS, 3 ] ]; const roguePool = [ - [modifierTypes.LEFTOVERS, 4], - [modifierTypes.SHELL_BELL, 4], - [modifierTypes.SOUL_DEW, 10], - [modifierTypes.SOOTHE_BELL, 3], - [modifierTypes.SCOPE_LENS, 1], - [modifierTypes.BATON, 1], - [modifierTypes.FOCUS_BAND, 5], - [modifierTypes.KINGS_ROCK, 3], - [modifierTypes.GRIP_CLAW, 5] + [ modifierTypes.LEFTOVERS, 4 ], + [ modifierTypes.SHELL_BELL, 4 ], + [ modifierTypes.SOUL_DEW, 10 ], + [ modifierTypes.SOOTHE_BELL, 3 ], + [ modifierTypes.SCOPE_LENS, 1 ], + [ modifierTypes.BATON, 1 ], + [ modifierTypes.FOCUS_BAND, 5 ], + [ modifierTypes.KINGS_ROCK, 3 ], + [ modifierTypes.GRIP_CLAW, 5 ] ]; const berryPool = [ - [BerryType.APICOT, 3], - [BerryType.ENIGMA, 2], - [BerryType.GANLON, 3], - [BerryType.LANSAT, 3], - [BerryType.LEPPA, 2], - [BerryType.LIECHI, 3], - [BerryType.LUM, 2], - [BerryType.PETAYA, 3], - [BerryType.SALAC, 2], - [BerryType.SITRUS, 2], - [BerryType.STARF, 3] + [ BerryType.APICOT, 3 ], + [ BerryType.ENIGMA, 2 ], + [ BerryType.GANLON, 3 ], + [ BerryType.LANSAT, 3 ], + [ BerryType.LEPPA, 2 ], + [ BerryType.LIECHI, 3 ], + [ BerryType.LUM, 2 ], + [ BerryType.PETAYA, 3 ], + [ BerryType.SALAC, 2 ], + [ BerryType.SITRUS, 2 ], + [ BerryType.STARF, 3 ] ]; let pool: any[]; @@ -493,7 +494,7 @@ function generateItemsOfTier(scene: BattleScene, pokemon: PlayerPokemon, numItem const newItemType = pool[randIndex]; let newMod: PokemonHeldItemModifierType; if (tier === "Berries") { - newMod = generateModifierType(scene, modifierTypes.BERRY, [newItemType[0]]) as PokemonHeldItemModifierType; + newMod = generateModifierType(scene, modifierTypes.BERRY, [ newItemType[0] ]) as PokemonHeldItemModifierType; } else { newMod = generateModifierType(scene, newItemType[0]) as PokemonHeldItemModifierType; } diff --git a/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts b/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts index 655cc3e937e..d7f71194f48 100644 --- a/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts +++ b/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts @@ -102,6 +102,7 @@ export const DancingLessonsEncounter: MysteryEncounter = text: `${namespace}:intro`, } ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -141,7 +142,7 @@ export const DancingLessonsEncounter: MysteryEncounter = scene.getEnemyParty().forEach(enemyPokemon => { scene.field.remove(enemyPokemon, true); }); - scene.currentBattle.enemyParty = [oricorio]; + scene.currentBattle.enemyParty = [ oricorio ]; scene.field.add(oricorio); // Spawns on offscreen field oricorio.x -= 300; @@ -153,14 +154,14 @@ export const DancingLessonsEncounter: MysteryEncounter = dataSource: oricorioData, isBoss: true, // Gets +1 to all stats except SPD on battle start - tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { queueEncounterMessage(pokemon.scene, `${namespace}:option.1.boss_enraged`); - pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF], 1)); + pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF ], 1)); } }], }; - encounter.enemyPartyConfigs = [config]; + encounter.enemyPartyConfigs = [ config ]; encounter.misc = { oricorioData }; @@ -187,13 +188,13 @@ export const DancingLessonsEncounter: MysteryEncounter = encounter.startOfBattleEffects.push({ sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.PLAYER], + targets: [ BattlerIndex.PLAYER ], move: new PokemonMove(Moves.REVELATION_DANCE), ignorePp: true }); await hideOricorioPokemon(scene); - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.BATON], fillRemaining: true }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.BATON ], fillRemaining: true }); await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]); }) .build() @@ -227,7 +228,7 @@ export const DancingLessonsEncounter: MysteryEncounter = }) .withOptionPhase(async (scene: BattleScene) => { // Learn its Dance - hideOricorioPokemon(scene); + await hideOricorioPokemon(scene); leaveEncounterWithoutBattle(scene, true); }) .build() @@ -302,7 +303,7 @@ export const DancingLessonsEncounter: MysteryEncounter = } } - hideOricorioPokemon(scene); + await hideOricorioPokemon(scene); await catchPokemon(scene, oricorio, null, PokeballType.POKEBALL, false); leaveEncounterWithoutBattle(scene, true); }) diff --git a/src/data/mystery-encounters/encounters/dark-deal-encounter.ts b/src/data/mystery-encounters/encounters/dark-deal-encounter.ts index 1678c82649b..4f7d5406dc3 100644 --- a/src/data/mystery-encounters/encounters/dark-deal-encounter.ts +++ b/src/data/mystery-encounters/encounters/dark-deal-encounter.ts @@ -118,6 +118,7 @@ export const DarkDealEncounter: MysteryEncounter = .withSceneWaveRangeRequirement(30, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1]) .withScenePartySizeRequirement(2, 6, true) // Must have at least 2 pokemon in party .withCatchAllowed(true) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -172,7 +173,7 @@ export const DarkDealEncounter: MysteryEncounter = // Starter egg tier, 35/50/10/5 %odds for tiers 6/7/8/9+ const roll = randSeedInt(100); const starterTier: number | [number, number] = - roll >= 65 ? 6 : roll >= 15 ? 7 : roll >= 5 ? 8 : [9, 10]; + roll >= 65 ? 6 : roll >= 15 ? 7 : roll >= 5 ? 8 : [ 9, 10 ]; const bossSpecies = getPokemonSpecies(getRandomSpeciesByStarterTier(starterTier, excludedBosses, bossTypes)); const pokemonConfig: EnemyPokemonConfig = { species: bossSpecies, @@ -187,9 +188,9 @@ export const DarkDealEncounter: MysteryEncounter = pokemonConfig.formIndex = 0; } const config: EnemyPartyConfig = { - pokemonConfigs: [pokemonConfig], + pokemonConfigs: [ pokemonConfig ], }; - return initBattleWithEnemyConfig(scene, config); + await initBattleWithEnemyConfig(scene, config); }) .build() ) diff --git a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts index 4db0595db26..4c7aa0cc73b 100644 --- a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts +++ b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts @@ -22,7 +22,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; const namespace = "mysteryEncounters/delibirdy"; /** Berries only */ -const OPTION_2_ALLOWED_MODIFIERS = ["BerryModifier", "PokemonInstantReviveModifier"]; +const OPTION_2_ALLOWED_MODIFIERS = [ "BerryModifier", "PokemonInstantReviveModifier" ]; /** Disallowed items are berries, Reviver Seeds, and Vitamins (form change items and fusion items are not PokemonHeldItemModifiers) */ const OPTION_3_DISALLOWED_MODIFIERS = [ @@ -84,6 +84,7 @@ export const DelibirdyEncounter: MysteryEncounter = text: `${namespace}:intro`, } ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) diff --git a/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts b/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts index 1505768f968..10034d19263 100644 --- a/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts +++ b/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts @@ -51,6 +51,7 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter = }, ]) .withAutoHideIntroVisuals(false) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) diff --git a/src/data/mystery-encounters/encounters/field-trip-encounter.ts b/src/data/mystery-encounters/encounters/field-trip-encounter.ts index 0a356f16b37..bf5fb28163b 100644 --- a/src/data/mystery-encounters/encounters/field-trip-encounter.ts +++ b/src/data/mystery-encounters/encounters/field-trip-encounter.ts @@ -52,6 +52,7 @@ export const FieldTripEncounter: MysteryEncounter = }, ]) .withAutoHideIntroVisuals(false) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -87,9 +88,9 @@ export const FieldTripEncounter: MysteryEncounter = const encounter = scene.currentBattle.mysteryEncounter!; if (encounter.misc.correctMove) { const modifiers = [ - generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.ATK])!, - generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.DEF])!, - generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!, + generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.ATK ])!, + generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.DEF ])!, + generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPD ])!, generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!, generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!, ]; @@ -133,9 +134,9 @@ export const FieldTripEncounter: MysteryEncounter = const encounter = scene.currentBattle.mysteryEncounter!; if (encounter.misc.correctMove) { const modifiers = [ - generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPATK])!, - generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPDEF])!, - generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!, + generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPATK ])!, + generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPDEF ])!, + generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPD ])!, generateModifierTypeOption(scene, modifierTypes.DIRE_HIT)!, generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!, ]; @@ -179,8 +180,8 @@ export const FieldTripEncounter: MysteryEncounter = const encounter = scene.currentBattle.mysteryEncounter!; if (encounter.misc.correctMove) { const modifiers = [ - generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.ACC])!, - generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [Stat.SPD])!, + generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.ACC ])!, + generateModifierTypeOption(scene, modifierTypes.TEMP_STAT_STAGE_BOOSTER, [ Stat.SPD ])!, generateModifierTypeOption(scene, modifierTypes.GREAT_BALL)!, generateModifierTypeOption(scene, modifierTypes.IV_SCANNER)!, generateModifierTypeOption(scene, modifierTypes.RARER_CANDY)!, @@ -227,7 +228,7 @@ function pokemonAndMoveChosen(scene: BattleScene, pokemon: PlayerPokemon, move: text: `${namespace}:correct_exp`, }, ]; - setEncounterExp(scene, [pokemon.id], 100); + setEncounterExp(scene, [ pokemon.id ], 100); } encounter.misc = { correctMove: correctMove, diff --git a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts index 917395bf226..052c44e17bb 100644 --- a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts +++ b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts @@ -87,7 +87,7 @@ export const FieryFalloutEncounter: MysteryEncounter = doubleBattle: true, disableSwitch: true, }; - encounter.enemyPartyConfigs = [config]; + encounter.enemyPartyConfigs = [ config ]; // Load hidden Volcarona sprites encounter.spriteConfigs = [ @@ -113,7 +113,7 @@ export const FieryFalloutEncounter: MysteryEncounter = ]; // Load animations/sfx for Volcarona moves - loadCustomMovesForEncounter(scene, [Moves.FIRE_SPIN, Moves.QUIVER_DANCE]); + loadCustomMovesForEncounter(scene, [ Moves.FIRE_SPIN, Moves.QUIVER_DANCE ]); scene.arena.trySetWeather(WeatherType.SUNNY, true); @@ -136,6 +136,7 @@ export const FieryFalloutEncounter: MysteryEncounter = return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -157,13 +158,13 @@ export const FieryFalloutEncounter: MysteryEncounter = encounter.startOfBattleEffects.push( { sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.PLAYER], + targets: [ BattlerIndex.PLAYER ], move: new PokemonMove(Moves.FIRE_SPIN), ignorePp: true }, { sourceBattlerIndex: BattlerIndex.ENEMY_2, - targets: [BattlerIndex.PLAYER_2], + targets: [ BattlerIndex.PLAYER_2 ], move: new PokemonMove(Moves.FIRE_SPIN), ignorePp: true }); @@ -229,12 +230,13 @@ export const FieryFalloutEncounter: MysteryEncounter = ], }) .withPreOptionPhase(async (scene: BattleScene) => { + // Do NOT await this, to prevent player from repeatedly pressing options transitionMysteryEncounterIntroVisuals(scene, false, false, 2000); }) .withOptionPhase(async (scene: BattleScene) => { // Fire types help calm the Volcarona const encounter = scene.currentBattle.mysteryEncounter!; - transitionMysteryEncounterIntroVisuals(scene); + await transitionMysteryEncounterIntroVisuals(scene); setEncounterRewards(scene, { fillRemaining: true }, undefined, @@ -244,7 +246,7 @@ export const FieryFalloutEncounter: MysteryEncounter = const primary = encounter.options[2].primaryPokemon!; - setEncounterExp(scene, [primary.id], getPokemonSpecies(Species.VOLCARONA).baseExp * 2); + setEncounterExp(scene, [ primary.id ], getPokemonSpecies(Species.VOLCARONA).baseExp * 2); leaveEncounterWithoutBattle(scene); }) .build() diff --git a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts index aa3bace67f0..380662ca817 100644 --- a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts +++ b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts @@ -65,16 +65,16 @@ export const FightOrFlightEncounter: MysteryEncounter = species: bossSpecies, dataSource: new PokemonData(bossPokemon), isBoss: true, - tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { queueEncounterMessage(pokemon.scene, `${namespace}:option.1.stat_boost`); // Randomly boost 1 stat 2 stages // Cannot boost Spd, Acc, or Evasion - pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [randSeedInt(4, 1)], 2)); + pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randSeedInt(4, 1) ], 2)); } }], }; - encounter.enemyPartyConfigs = [config]; + encounter.enemyPartyConfigs = [ config ]; // Calculate item // Waves 10-40 GREAT, 60-120 ULTRA, 120-160 ROGUE, 160-180 MASTER @@ -90,7 +90,7 @@ export const FightOrFlightEncounter: MysteryEncounter = let item: ModifierTypeOption | null = null; // TMs and Candy Jar excluded from possible rewards as they're too swingy in value for a singular item reward while (!item || item.type.id.includes("TM_") || item.type.id === "CANDY_JAR") { - item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [tier], allowLuckUpgrades: false })[0]; + item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [ tier ], allowLuckUpgrades: false })[0]; } encounter.setDialogueToken("itemName", item.type.name); encounter.misc = item; @@ -120,6 +120,7 @@ export const FightOrFlightEncounter: MysteryEncounter = return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -137,7 +138,7 @@ export const FightOrFlightEncounter: MysteryEncounter = // Pick battle // Pokemon will randomly boost 1 stat by 2 stages const item = scene.currentBattle.mysteryEncounter!.misc as ModifierTypeOption; - setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ item ], fillRemaining: false }); await initBattleWithEnemyConfig(scene, scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]); } ) @@ -159,7 +160,7 @@ export const FightOrFlightEncounter: MysteryEncounter = // Pick steal const encounter = scene.currentBattle.mysteryEncounter!; const item = scene.currentBattle.mysteryEncounter!.misc as ModifierTypeOption; - setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ item ], fillRemaining: false }); // Use primaryPokemon to execute the thievery const primaryPokemon = encounter.options[1].primaryPokemon!; diff --git a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts index c690faf28b7..b843a929c08 100644 --- a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts +++ b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts @@ -76,6 +76,7 @@ export const FunAndGamesEncounter: MysteryEncounter = text: `${namespace}:intro_dialogue`, }, ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -151,7 +152,7 @@ export const FunAndGamesEncounter: MysteryEncounter = }, async (scene: BattleScene) => { // Leave encounter with no rewards or exp - transitionMysteryEncounterIntroVisuals(scene, true, true); + await transitionMysteryEncounterIntroVisuals(scene, true, true); leaveEncounterWithoutBattle(scene, true); return true; } @@ -197,7 +198,7 @@ async function summonPlayerPokemon(scene: BattleScene) { const enemySpecies = getPokemonSpecies(Species.WOBBUFFET); scene.currentBattle.enemyParty = []; const wobbuffet = scene.addEnemyPokemon(enemySpecies, encounter.misc.playerPokemon.level, TrainerSlot.NONE, false); - wobbuffet.ivs = [0, 0, 0, 0, 0, 0]; + wobbuffet.ivs = [ 0, 0, 0, 0, 0, 0 ]; wobbuffet.setNature(Nature.MILD); wobbuffet.setAlpha(0); wobbuffet.setVisible(false); @@ -256,15 +257,15 @@ function handleNextTurn(scene: BattleScene) { let isHealPhase = false; if (healthRatio < 0.03) { // Grand prize - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MULTI_LENS], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.MULTI_LENS ], fillRemaining: false }); resultMessageKey = `${namespace}:best_result`; } else if (healthRatio < 0.15) { // 2nd prize - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SCOPE_LENS], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.SCOPE_LENS ], fillRemaining: false }); resultMessageKey = `${namespace}:great_result`; } else if (healthRatio < 0.33) { // 3rd prize - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.WIDE_LENS], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.WIDE_LENS ], fillRemaining: false }); resultMessageKey = `${namespace}:good_result`; } else { // No prize @@ -411,7 +412,7 @@ function hideShowmanIntroSprite(scene: BattleScene) { // Slide the Wobbuffet and Game over slightly scene.tweens.add({ - targets: [wobbuffet, carnivalGame], + targets: [ wobbuffet, carnivalGame ], x: "+=16", ease: "Sine.easeInOut", duration: 750 diff --git a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts index cc66bdfb4c9..376bdf0c95d 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -35,15 +35,15 @@ const WONDER_TRADE_SHINY_CHANCE = 512; const MAX_WONDER_TRADE_SHINY_CHANCE = 4096; const LEGENDARY_TRADE_POOLS = { - 1: [Species.RATTATA, Species.PIDGEY, Species.WEEDLE], - 2: [Species.SENTRET, Species.HOOTHOOT, Species.LEDYBA], - 3: [Species.POOCHYENA, Species.ZIGZAGOON, Species.TAILLOW], - 4: [Species.BIDOOF, Species.STARLY, Species.KRICKETOT], - 5: [Species.PATRAT, Species.PURRLOIN, Species.PIDOVE], - 6: [Species.BUNNELBY, Species.LITLEO, Species.SCATTERBUG], - 7: [Species.PIKIPEK, Species.YUNGOOS, Species.ROCKRUFF], - 8: [Species.SKWOVET, Species.WOOLOO, Species.ROOKIDEE], - 9: [Species.LECHONK, Species.FIDOUGH, Species.TAROUNTULA] + 1: [ Species.RATTATA, Species.PIDGEY, Species.WEEDLE ], + 2: [ Species.SENTRET, Species.HOOTHOOT, Species.LEDYBA ], + 3: [ Species.POOCHYENA, Species.ZIGZAGOON, Species.TAILLOW ], + 4: [ Species.BIDOOF, Species.STARLY, Species.KRICKETOT ], + 5: [ Species.PATRAT, Species.PURRLOIN, Species.PIDOVE ], + 6: [ Species.BUNNELBY, Species.LITLEO, Species.SCATTERBUG ], + 7: [ Species.PIKIPEK, Species.YUNGOOS, Species.ROCKRUFF ], + 8: [ Species.SKWOVET, Species.WOOLOO, Species.ROOKIDEE ], + 9: [ Species.LECHONK, Species.FIDOUGH, Species.TAROUNTULA ] }; /** Exclude Paradox mons as they aren't considered legendary/mythical */ @@ -96,6 +96,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = text: `${namespace}:intro`, } ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -387,18 +388,18 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = let item: ModifierTypeOption | null = null; // TMs excluded from possible rewards while (!item || item.type.id.includes("TM_")) { - item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [tier], allowLuckUpgrades: false })[0]; + item = getPlayerModifierTypeOptions(1, scene.getParty(), [], { guaranteedModifierTiers: [ tier ], allowLuckUpgrades: false })[0]; } encounter.setDialogueToken("itemName", item.type.name); - setEncounterRewards(scene, { guaranteedModifierTypeOptions: [item], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ item ], fillRemaining: false }); // Remove the chosen modifier if its stacks go to 0 modifier.stackCount -= 1; if (modifier.stackCount === 0) { scene.removeModifier(modifier); } - scene.updateModifiers(true, true); + await scene.updateModifiers(true, true); // Generate a trainer name const traderName = generateRandomTraderName(); @@ -650,7 +651,7 @@ function doPokemonTradeSequence(scene: BattleScene, tradedPokemon: PlayerPokemon // addPokeballOpenParticles(scene, tradedPokemon.x, tradedPokemon.y, tradedPokemon.pokeball); scene.tweens.add({ - targets: [tradedPokemonTintSprite, tradedPokemonSprite], + targets: [ tradedPokemonTintSprite, tradedPokemonSprite ], duration: 500, ease: "Sine.easeIn", scale: 0.25, @@ -726,7 +727,7 @@ function doPokemonTradeFlyBySequence(scene: BattleScene, tradedPokemonSprite: Ph duration: FADE_DELAY, onComplete: () => { scene.tweens.add({ - targets: [receivedPokemonSprite, tradedPokemonSprite], + targets: [ receivedPokemonSprite, tradedPokemonSprite ], y: tradeBaseBg.displayWidth / 2 - 100, ease: "Cubic.easeInOut", duration: BASE_ANIM_DURATION * 3, diff --git a/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts index 27b3bdd8cf7..8e7ea52a967 100644 --- a/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts +++ b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts @@ -10,7 +10,7 @@ import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encount import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; -import {PokemonMove} from "#app/field/pokemon"; +import { PokemonMove } from "#app/field/pokemon"; const OPTION_1_REQUIRED_MOVE = Moves.SURF; const OPTION_2_REQUIRED_MOVE = Moves.FLY; @@ -50,6 +50,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -128,7 +129,7 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with * * @param scene Battle scene */ -async function handlePokemonGuidingYouPhase(scene: BattleScene) { +function handlePokemonGuidingYouPhase(scene: BattleScene) { const laprasSpecies = getPokemonSpecies(Species.LAPRAS); const { mysteryEncounter } = scene.currentBattle; diff --git a/src/data/mystery-encounters/encounters/mysterious-challengers-encounter.ts b/src/data/mystery-encounters/encounters/mysterious-challengers-encounter.ts index abf19a5e2f9..7fdd29d36a2 100644 --- a/src/data/mystery-encounters/encounters/mysterious-challengers-encounter.ts +++ b/src/data/mystery-encounters/encounters/mysterious-challengers-encounter.ts @@ -131,6 +131,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter = return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -149,14 +150,14 @@ export const MysteriousChallengersEncounter: MysteryEncounter = // Spawn standard trainer battle with memory mushroom reward const config: EnemyPartyConfig = encounter.enemyPartyConfigs[0]; - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM], fillRemaining: true }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.TM_COMMON, modifierTypes.TM_GREAT, modifierTypes.MEMORY_MUSHROOM ], fillRemaining: true }); // Seed offsets to remove possibility of different trainers having exact same teams - let ret; + let initBattlePromise: Promise; scene.executeWithSeedOffset(() => { - ret = initBattleWithEnemyConfig(scene, config); + initBattlePromise = initBattleWithEnemyConfig(scene, config); }, scene.currentBattle.waveIndex * 10); - return ret; + await initBattlePromise!; } ) .withSimpleOption( @@ -174,14 +175,14 @@ export const MysteriousChallengersEncounter: MysteryEncounter = // Spawn hard fight const config: EnemyPartyConfig = encounter.enemyPartyConfigs[1]; - setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT], fillRemaining: true }); + setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ULTRA, ModifierTier.ULTRA, ModifierTier.GREAT, ModifierTier.GREAT ], fillRemaining: true }); // Seed offsets to remove possibility of different trainers having exact same teams - let ret; + let initBattlePromise: Promise; scene.executeWithSeedOffset(() => { - ret = initBattleWithEnemyConfig(scene, config); + initBattlePromise = initBattleWithEnemyConfig(scene, config); }, scene.currentBattle.waveIndex * 100); - return ret; + await initBattlePromise!; } ) .withSimpleOption( @@ -202,14 +203,14 @@ export const MysteriousChallengersEncounter: MysteryEncounter = // To avoid player level snowballing from picking this option encounter.expMultiplier = 0.9; - setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT], fillRemaining: true }); + setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT ], fillRemaining: true }); // Seed offsets to remove possibility of different trainers having exact same teams - let ret; + let initBattlePromise: Promise; scene.executeWithSeedOffset(() => { - ret = initBattleWithEnemyConfig(scene, config); + initBattlePromise = initBattleWithEnemyConfig(scene, config); }, scene.currentBattle.waveIndex * 1000); - return ret; + await initBattlePromise!; } ) .withOutroDialogue([ diff --git a/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts b/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts index 9221cde0844..693d935ae17 100644 --- a/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts +++ b/src/data/mystery-encounters/encounters/mysterious-chest-encounter.ts @@ -61,6 +61,7 @@ export const MysteriousChestEncounter: MysteryEncounter = text: `${namespace}:intro`, } ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -76,12 +77,12 @@ export const MysteriousChestEncounter: MysteryEncounter = species: getPokemonSpecies(Species.GIMMIGHOUL), formIndex: 0, isBoss: true, - moveSet: [Moves.NASTY_PLOT, Moves.SHADOW_BALL, Moves.POWER_GEM, Moves.THIEF] + moveSet: [ Moves.NASTY_PLOT, Moves.SHADOW_BALL, Moves.POWER_GEM, Moves.THIEF ] } ], }; - encounter.enemyPartyConfigs = [config]; + encounter.enemyPartyConfigs = [ config ]; encounter.setDialogueToken("gimmighoulName", getPokemonSpecies(Species.GIMMIGHOUL).getName()); encounter.setDialogueToken("trapPercent", TRAP_PERCENT.toString()); @@ -157,13 +158,13 @@ export const MysteriousChestEncounter: MysteryEncounter = leaveEncounterWithoutBattle(scene); } else if (roll >= RAND_LENGTH - COMMON_REWARDS_PERCENT - ULTRA_REWARDS_PERCENT - ROGUE_REWARDS_PERCENT) { // Choose between 2 ROGUE tier items (10%) - setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE] }); + setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE ]}); // Display result message then proceed to rewards queueEncounterMessage(scene, `${namespace}:option.1.great`); leaveEncounterWithoutBattle(scene); } else if (roll >= RAND_LENGTH - COMMON_REWARDS_PERCENT - ULTRA_REWARDS_PERCENT - ROGUE_REWARDS_PERCENT - MASTER_REWARDS_PERCENT) { // Choose 1 MASTER tier item (5%) - setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.MASTER] }); + setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.MASTER ]}); // Display result message then proceed to rewards queueEncounterMessage(scene, `${namespace}:option.1.amazing`); leaveEncounterWithoutBattle(scene); @@ -183,7 +184,7 @@ export const MysteriousChestEncounter: MysteryEncounter = scene.unshiftPhase(new GameOverPhase(scene)); } else { // Show which Pokemon was KOed, then start battle against Gimmighoul - transitionMysteryEncounterIntroVisuals(scene, true, true, 500); + await transitionMysteryEncounterIntroVisuals(scene, true, true, 500); setEncounterRewards(scene, { fillRemaining: true }); await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]); } diff --git a/src/data/mystery-encounters/encounters/part-timer-encounter.ts b/src/data/mystery-encounters/encounters/part-timer-encounter.ts index f7eb2f2f1b4..17a3a366569 100644 --- a/src/data/mystery-encounters/encounters/part-timer-encounter.ts +++ b/src/data/mystery-encounters/encounters/part-timer-encounter.ts @@ -69,6 +69,7 @@ export const PartTimerEncounter: MysteryEncounter = return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -94,7 +95,7 @@ export const PartTimerEncounter: MysteryEncounter = // Calculation from Pokemon.calculateStats const baselineValue = Math.floor(((2 * 90 + 16) * pokemon.level) * 0.01) + 5; const percentDiff = (pokemon.getStat(Stat.SPD) - baselineValue) / baselineValue; - const moneyMultiplier = Math.min(Math.max(2.5 * (1+ percentDiff), 1), 4); + const moneyMultiplier = Math.min(Math.max(2.5 * (1 + percentDiff), 1), 4); encounter.misc = { moneyMultiplier diff --git a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts index be5b9023eea..0ee3c57b0a2 100644 --- a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts +++ b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts @@ -23,7 +23,7 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounters/safariZone"; -const TRAINER_THROW_ANIMATION_TIMES = [512, 184, 768]; +const TRAINER_THROW_ANIMATION_TIMES = [ 512, 184, 768 ]; const SAFARI_MONEY_MULTIPLIER = 2; @@ -54,6 +54,7 @@ export const SafariZoneEncounter: MysteryEncounter = text: `${namespace}:intro`, }, ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -260,7 +261,7 @@ async function summonSafariPokemon(scene: BattleScene) { let enemySpecies; let pokemon; scene.executeWithSeedOffset(() => { - enemySpecies = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false)); + enemySpecies = getPokemonSpecies(getRandomSpeciesByStarterTier([ 0, 5 ], undefined, undefined, false, false, false)); const level = scene.currentBattle.getLevelForWave(); enemySpecies = getPokemonSpecies(enemySpecies.getWildSpeciesForLevel(level, true, false, scene.gameMode)); pokemon = scene.addEnemyPokemon(enemySpecies, level, TrainerSlot.NONE, false); @@ -302,13 +303,16 @@ async function summonSafariPokemon(scene: BattleScene) { scene.unshiftPhase(new SummonPhase(scene, 0, false)); encounter.setDialogueToken("pokemonName", getPokemonNameWithAffix(pokemon)); - showEncounterText(scene, getEncounterText(scene, "battle:singleWildAppeared") ?? "", null, 1500, false) - .then(() => { - const ivScannerModifier = scene.findModifier(m => m instanceof IvScannerModifier); - if (ivScannerModifier) { - scene.pushPhase(new ScanIvsPhase(scene, pokemon.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6))); - } - }); + + // TODO: If we await showEncounterText here, then the text will display without + // the wild Pokemon on screen, but if we don't await it, then the text never + // shows up and the IV scanner breaks. For now, we place the IV scanner code + // separately so that at least the IV scanner works. + + const ivScannerModifier = scene.findModifier(m => m instanceof IvScannerModifier); + if (ivScannerModifier) { + scene.pushPhase(new ScanIvsPhase(scene, pokemon.getBattlerIndex(), Math.min(ivScannerModifier.getStackCount() * 2, 6))); + } } function throwPokeball(scene: BattleScene, pokemon: EnemyPokemon): Promise { diff --git a/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts b/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts index aaf08fadfcb..abe75797834 100644 --- a/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts +++ b/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts @@ -33,7 +33,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = .withEncounterTier(MysteryEncounterTier.COMMON) .withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES) .withSceneRequirement(new MoneyRequirement(0, VITAMIN_DEALER_CHEAP_PRICE_MULTIPLIER)) // Must have the money for at least the cheap deal - .withPrimaryPokemonHealthRatioRequirement([0.51, 1]) // At least 1 Pokemon must have above half HP + .withPrimaryPokemonHealthRatioRequirement([ 0.51, 1 ]) // At least 1 Pokemon must have above half HP .withIntroSpriteConfigs([ { spriteKey: Species.KROOKODILE.toString(), @@ -62,6 +62,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = speaker: `${namespace}:speaker`, }, ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -140,8 +141,8 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = chosenPokemon.nature = newNature; encounter.setDialogueToken("newNature", getNatureName(newNature)); queueEncounterMessage(scene, `${namespace}:cheap_side_effects`); - setEncounterExp(scene, [chosenPokemon.id], 100); - chosenPokemon.updateInfo(); + setEncounterExp(scene, [ chosenPokemon.id ], 100); + await chosenPokemon.updateInfo(); }) .build() ) @@ -201,9 +202,9 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = const chosenPokemon = encounter.misc.chosenPokemon; queueEncounterMessage(scene, `${namespace}:no_bad_effects`); - setEncounterExp(scene, [chosenPokemon.id], 100); + setEncounterExp(scene, [ chosenPokemon.id ], 100); - chosenPokemon.updateInfo(); + await chosenPokemon.updateInfo(); }) .build() ) diff --git a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts index 0545fa5f0fd..c53040a14a5 100644 --- a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts +++ b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts @@ -60,15 +60,15 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = const pokemonConfig: EnemyPokemonConfig = { species: bossSpecies, isBoss: true, - status: [StatusEffect.SLEEP, 5], // Extra turns on timer for Snorlax's start of fight moves - moveSet: [Moves.REST, Moves.SLEEP_TALK, Moves.CRUNCH, Moves.GIGA_IMPACT], + status: [ StatusEffect.SLEEP, 5 ], // Extra turns on timer for Snorlax's start of fight moves + moveSet: [ Moves.REST, Moves.SLEEP_TALK, Moves.CRUNCH, Moves.GIGA_IMPACT ], modifierConfigs: [ { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ]) as PokemonHeldItemModifierType, stackCount: 2 }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.ENIGMA]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.ENIGMA ]) as PokemonHeldItemModifierType, stackCount: 2 }, ], @@ -77,17 +77,18 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = }; const config: EnemyPartyConfig = { levelAdditiveModifier: 0.5, - pokemonConfigs: [pokemonConfig], + pokemonConfigs: [ pokemonConfig ], }; - encounter.enemyPartyConfigs = [config]; + encounter.enemyPartyConfigs = [ config ]; // Load animations/sfx for Snorlax fight start moves - loadCustomMovesForEncounter(scene, [Moves.SNORE]); + loadCustomMovesForEncounter(scene, [ Moves.SNORE ]); encounter.setDialogueToken("snorlaxName", getPokemonSpecies(Species.SNORLAX).getName()); return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -104,17 +105,17 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = async (scene: BattleScene) => { // Pick battle const encounter = scene.currentBattle.mysteryEncounter!; - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], fillRemaining: true}); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.LEFTOVERS ], fillRemaining: true }); encounter.startOfBattleEffects.push( { sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.PLAYER], + targets: [ BattlerIndex.PLAYER ], move: new PokemonMove(Moves.SNORE), ignorePp: true }, { sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.PLAYER], + targets: [ BattlerIndex.PLAYER ], move: new PokemonMove(Moves.SNORE), ignorePp: true }); @@ -156,7 +157,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = .withOptionPhase(async (scene: BattleScene) => { // Steal the Snorlax's Leftovers const instance = scene.currentBattle.mysteryEncounter!; - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.LEFTOVERS ], fillRemaining: false }); // Snorlax exp to Pokemon that did the stealing setEncounterExp(scene, instance.primaryPokemon!.id, getPokemonSpecies(Species.SNORLAX).baseExp); leaveEncounterWithoutBattle(scene); diff --git a/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts b/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts index f685bdae2a1..e8f11f02e18 100644 --- a/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts +++ b/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts @@ -26,8 +26,8 @@ import { getEncounterPokemonLevelForWave, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIF const namespace = "mysteryEncounters/teleportingHijinks"; const MONEY_COST_MULTIPLIER = 1.75; -const BIOME_CANDIDATES = [Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND, Biome.WASTELAND, Biome.DOJO]; -const MACHINE_INTERFACING_TYPES = [Type.ELECTRIC, Type.STEEL]; +const BIOME_CANDIDATES = [ Biome.SPACE, Biome.FAIRY_CAVE, Biome.LABORATORY, Biome.ISLAND, Biome.WASTELAND, Biome.DOJO ]; +const MACHINE_INTERFACING_TYPES = [ Type.ELECTRIC, Type.STEEL ]; /** * Teleporting Hijinks encounter. @@ -38,7 +38,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter = MysteryEncounterBuilder.withEncounterType(MysteryEncounterType.TELEPORTING_HIJINKS) .withEncounterTier(MysteryEncounterTier.COMMON) .withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES) - .withSceneRequirement(new WaveModulusRequirement([1, 2, 3], 10)) // Must be in first 3 waves after boss wave + .withSceneRequirement(new WaveModulusRequirement([ 1, 2, 3 ], 10)) // Must be in first 3 waves after boss wave .withSceneRequirement(new MoneyRequirement(0, MONEY_COST_MULTIPLIER)) // Must be able to pay teleport cost .withAutoHideIntroVisuals(false) .withCatchAllowed(true) @@ -58,6 +58,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter = text: `${namespace}:intro`, } ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -145,10 +146,10 @@ export const TeleportingHijinksEncounter: MysteryEncounter = }], }; - const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.STEEL])!; - const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.ELECTRIC])!; - setEncounterRewards(scene, { guaranteedModifierTypeOptions: [magnet, metalCoat], fillRemaining: true }); - transitionMysteryEncounterIntroVisuals(scene, true, true); + const magnet = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.STEEL ])!; + const metalCoat = generateModifierTypeOption(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.ELECTRIC ])!; + setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ magnet, metalCoat ], fillRemaining: true }); + await transitionMysteryEncounterIntroVisuals(scene, true, true); await initBattleWithEnemyConfig(scene, config); } ) @@ -163,7 +164,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) { // Show dialogue and transition biome await showEncounterText(scene, `${namespace}:transport`); - await Promise.all([animateBiomeChange(scene, newBiome), transitionMysteryEncounterIntroVisuals(scene)]); + await Promise.all([ animateBiomeChange(scene, newBiome), transitionMysteryEncounterIntroVisuals(scene) ]); scene.playBgm(); await showEncounterText(scene, `${namespace}:attacked`); @@ -175,8 +176,8 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) { // Defense/Spd buffs below wave 50, +1 to all stats otherwise const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ? - [Stat.DEF, Stat.SPDEF, Stat.SPD] : - [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD]; + [ Stat.DEF, Stat.SPDEF, Stat.SPD ] : + [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ]; const config: EnemyPartyConfig = { pokemonConfigs: [{ @@ -184,7 +185,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) { species: bossSpecies, dataSource: new PokemonData(bossPokemon), isBoss: true, - tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { queueEncounterMessage(pokemon.scene, `${namespace}:boss_enraged`); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1)); @@ -198,7 +199,7 @@ async function doBiomeTransitionDialogueAndBattleInit(scene: BattleScene) { async function animateBiomeChange(scene: BattleScene, nextBiome: Biome) { return new Promise(resolve => { scene.tweens.add({ - targets: [scene.arenaEnemy, scene.lastEnemyTrainer], + targets: [ scene.arenaEnemy, scene.lastEnemyTrainer ], x: "+=300", duration: 2000, onComplete: () => { @@ -214,7 +215,7 @@ async function animateBiomeChange(scene: BattleScene, nextBiome: Biome) { scene.arenaPlayerTransition.setVisible(true); scene.tweens.add({ - targets: [scene.arenaPlayer, scene.arenaBgTransition, scene.arenaPlayerTransition], + targets: [ scene.arenaPlayer, scene.arenaBgTransition, scene.arenaPlayerTransition ], duration: 1000, ease: "Sine.easeInOut", alpha: (target: any) => target === scene.arenaPlayer ? 0 : 1, diff --git a/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts b/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts index af34ea368fc..2202285a4b5 100644 --- a/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter.ts @@ -48,29 +48,29 @@ class BreederSpeciesEvolution { } const POOL_1_POKEMON: (Species | BreederSpeciesEvolution)[][] = [ - [Species.MUNCHLAX, new BreederSpeciesEvolution(Species.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE)], - [Species.HAPPINY, new BreederSpeciesEvolution(Species.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE)], - [Species.MAGBY, new BreederSpeciesEvolution(Species.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE)], - [Species.ELEKID, new BreederSpeciesEvolution(Species.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE)], - [Species.RIOLU, new BreederSpeciesEvolution(Species.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE)], - [Species.BUDEW, new BreederSpeciesEvolution(Species.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE)], - [Species.TOXEL, new BreederSpeciesEvolution(Species.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE)], - [Species.MIME_JR, new BreederSpeciesEvolution(Species.GALAR_MR_MIME, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE)] + [ Species.MUNCHLAX, new BreederSpeciesEvolution(Species.SNORLAX, SECOND_STAGE_EVOLUTION_WAVE) ], + [ Species.HAPPINY, new BreederSpeciesEvolution(Species.CHANSEY, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.BLISSEY, FINAL_STAGE_EVOLUTION_WAVE) ], + [ Species.MAGBY, new BreederSpeciesEvolution(Species.MAGMAR, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MAGMORTAR, FINAL_STAGE_EVOLUTION_WAVE) ], + [ Species.ELEKID, new BreederSpeciesEvolution(Species.ELECTABUZZ, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ELECTIVIRE, FINAL_STAGE_EVOLUTION_WAVE) ], + [ Species.RIOLU, new BreederSpeciesEvolution(Species.LUCARIO, SECOND_STAGE_EVOLUTION_WAVE) ], + [ Species.BUDEW, new BreederSpeciesEvolution(Species.ROSELIA, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ROSERADE, FINAL_STAGE_EVOLUTION_WAVE) ], + [ Species.TOXEL, new BreederSpeciesEvolution(Species.TOXTRICITY, SECOND_STAGE_EVOLUTION_WAVE) ], + [ Species.MIME_JR, new BreederSpeciesEvolution(Species.GALAR_MR_MIME, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.MR_RIME, FINAL_STAGE_EVOLUTION_WAVE) ] ]; const POOL_2_POKEMON: (Species | BreederSpeciesEvolution)[][] = [ - [Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.RAICHU, FINAL_STAGE_EVOLUTION_WAVE)], - [Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE)], - [Species.JYNX], - [Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE)], - [Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE)], - [Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE)], - [Species.IGGLYBUFF, new BreederSpeciesEvolution(Species.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE)], - [Species.AZURILL, new BreederSpeciesEvolution(Species.MARILL, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE)], - [Species.WYNAUT, new BreederSpeciesEvolution(Species.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE)], - [Species.CHINGLING, new BreederSpeciesEvolution(Species.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE)], - [Species.BONSLY, new BreederSpeciesEvolution(Species.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE)], - [Species.MANTYKE, new BreederSpeciesEvolution(Species.MANTINE, SECOND_STAGE_EVOLUTION_WAVE)] + [ Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.RAICHU, FINAL_STAGE_EVOLUTION_WAVE) ], + [ Species.PICHU, new BreederSpeciesEvolution(Species.PIKACHU, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.ALOLA_RAICHU, FINAL_STAGE_EVOLUTION_WAVE) ], + [ Species.SMOOCHUM, new BreederSpeciesEvolution(Species.JYNX, SECOND_STAGE_EVOLUTION_WAVE) ], + [ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONLEE, SECOND_STAGE_EVOLUTION_WAVE) ], + [ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONCHAN, SECOND_STAGE_EVOLUTION_WAVE) ], + [ Species.TYROGUE, new BreederSpeciesEvolution(Species.HITMONTOP, SECOND_STAGE_EVOLUTION_WAVE) ], + [ Species.IGGLYBUFF, new BreederSpeciesEvolution(Species.JIGGLYPUFF, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.WIGGLYTUFF, FINAL_STAGE_EVOLUTION_WAVE) ], + [ Species.AZURILL, new BreederSpeciesEvolution(Species.MARILL, FIRST_STAGE_EVOLUTION_WAVE), new BreederSpeciesEvolution(Species.AZUMARILL, FINAL_STAGE_EVOLUTION_WAVE) ], + [ Species.WYNAUT, new BreederSpeciesEvolution(Species.WOBBUFFET, SECOND_STAGE_EVOLUTION_WAVE) ], + [ Species.CHINGLING, new BreederSpeciesEvolution(Species.CHIMECHO, SECOND_STAGE_EVOLUTION_WAVE) ], + [ Species.BONSLY, new BreederSpeciesEvolution(Species.SUDOWOODO, SECOND_STAGE_EVOLUTION_WAVE) ], + [ Species.MANTYKE, new BreederSpeciesEvolution(Species.MANTINE, SECOND_STAGE_EVOLUTION_WAVE) ] ]; /** @@ -138,7 +138,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = encounter.setDialogueToken("pokemon3Name", pokemon3.getNameToRender()); // Dialogue and egg calcs for Pokemon 1 - const [pokemon1CommonEggs, pokemon1RareEggs] = calculateEggRewardsForPokemon(pokemon1); + const [ pokemon1CommonEggs, pokemon1RareEggs ] = calculateEggRewardsForPokemon(pokemon1); let pokemon1Tooltip = getEncounterText(scene, `${namespace}:option.1.tooltip_base`)!; if (pokemon1RareEggs > 0) { const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon1RareEggs, rarity: i18next.t("egg:greatTier") }); @@ -153,7 +153,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = encounter.options[0].dialogue!.buttonTooltip = pokemon1Tooltip; // Dialogue and egg calcs for Pokemon 2 - const [pokemon2CommonEggs, pokemon2RareEggs] = calculateEggRewardsForPokemon(pokemon2); + const [ pokemon2CommonEggs, pokemon2RareEggs ] = calculateEggRewardsForPokemon(pokemon2); let pokemon2Tooltip = getEncounterText(scene, `${namespace}:option.2.tooltip_base`)!; if (pokemon2RareEggs > 0) { const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2RareEggs, rarity: i18next.t("egg:greatTier") }); @@ -168,7 +168,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = encounter.options[1].dialogue!.buttonTooltip = pokemon2Tooltip; // Dialogue and egg calcs for Pokemon 3 - const [pokemon3CommonEggs, pokemon3RareEggs] = calculateEggRewardsForPokemon(pokemon3); + const [ pokemon3CommonEggs, pokemon3RareEggs ] = calculateEggRewardsForPokemon(pokemon3); let pokemon3Tooltip = getEncounterText(scene, `${namespace}:option.3.tooltip_base`)!; if (pokemon3RareEggs > 0) { const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon3RareEggs, rarity: i18next.t("egg:greatTier") }); @@ -196,6 +196,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -244,7 +245,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = } encounter.onGameOver = onGameOver; - initBattleWithEnemyConfig(scene, config); + await initBattleWithEnemyConfig(scene, config); }) .withPostOptionPhase(async (scene: BattleScene) => { await doPostEncounterCleanup(scene); @@ -296,7 +297,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = } encounter.onGameOver = onGameOver; - initBattleWithEnemyConfig(scene, config); + await initBattleWithEnemyConfig(scene, config); }) .withPostOptionPhase(async (scene: BattleScene) => { await doPostEncounterCleanup(scene); @@ -348,7 +349,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = } encounter.onGameOver = onGameOver; - initBattleWithEnemyConfig(scene, config); + await initBattleWithEnemyConfig(scene, config); }) .withPostOptionPhase(async (scene: BattleScene) => { await doPostEncounterCleanup(scene); @@ -381,11 +382,11 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig { abilityIndex: 1, // Magic Guard shiny: false, nature: Nature.ADAMANT, - moveSet: [Moves.METEOR_MASH, Moves.FIRE_PUNCH, Moves.ICE_PUNCH, Moves.THUNDER_PUNCH], - ivs: [31, 31, 31, 31, 31, 31], + moveSet: [ Moves.METEOR_MASH, Moves.FIRE_PUNCH, Moves.ICE_PUNCH, Moves.THUNDER_PUNCH ], + ivs: [ 31, 31, 31, 31, 31, 31 ], modifierConfigs: [ { - modifier: generateModifierType(scene, modifierTypes.TERA_SHARD, [Type.STEEL]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.TERA_SHARD, [ Type.STEEL ]) as PokemonHeldItemModifierType, } ] } @@ -402,8 +403,8 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig { shiny: true, variant: 1, nature: Nature.MODEST, - moveSet: [Moves.MOONBLAST, Moves.MYSTICAL_FIRE, Moves.ICE_BEAM, Moves.THUNDERBOLT], - ivs: [31, 31, 31, 31, 31, 31] + moveSet: [ Moves.MOONBLAST, Moves.MYSTICAL_FIRE, Moves.ICE_BEAM, Moves.THUNDERBOLT ], + ivs: [ 31, 31, 31, 31, 31, 31 ] }, { nickname: i18next.t(`${namespace}:cleffa_3_nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName() }), @@ -413,8 +414,8 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig { shiny: true, variant: 2, nature: Nature.BOLD, - moveSet: [Moves.TRI_ATTACK, Moves.STORED_POWER, Moves.TAKE_HEART, Moves.MOONLIGHT], - ivs: [31, 31, 31, 31, 31, 31] + moveSet: [ Moves.TRI_ATTACK, Moves.STORED_POWER, Moves.TAKE_HEART, Moves.MOONLIGHT ], + ivs: [ 31, 31, 31, 31, 31, 31 ] }); } else { // Second member from pool 1 @@ -425,12 +426,12 @@ function getPartyConfig(scene: BattleScene): EnemyPartyConfig { baseConfig.pokemonConfigs!.push({ species: getPokemonSpecies(pool1Species), isBoss: false, - ivs: [31, 31, 31, 31, 31, 31] + ivs: [ 31, 31, 31, 31, 31, 31 ] }, { species: getPokemonSpecies(pool2Species), isBoss: false, - ivs: [31, 31, 31, 31, 31, 31] + ivs: [ 31, 31, 31, 31, 31, 31 ] }); } @@ -472,7 +473,7 @@ function calculateEggRewardsForPokemon(pokemon: PlayerPokemon): [number, number] // 1 Common egg for every point leftover numCommons += totalPoints % 4; - return [numCommons, numRares]; + return [ numCommons, numRares ]; } function getEggOptions(scene: BattleScene, commonEggs: number, rareEggs: number) { @@ -497,7 +498,7 @@ function getEggOptions(scene: BattleScene, commonEggs: number, rareEggs: number) pulled: false, sourceType: EggSourceType.EVENT, eggDescriptor: eggDescription, - tier: EggTier.GREAT + tier: EggTier.RARE }); } } diff --git a/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts b/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts index 5486c130a28..95f359547e4 100644 --- a/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts @@ -53,18 +53,19 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = speaker: `${namespace}:speaker`, }, ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) .withOnInit((scene: BattleScene) => { const encounter = scene.currentBattle.mysteryEncounter!; - let species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false)); + let species = getPokemonSpecies(getRandomSpeciesByStarterTier([ 0, 5 ], undefined, undefined, false, false, false)); let tries = 0; // Reroll any species that don't have HAs while ((isNullOrUndefined(species.abilityHidden) || species.abilityHidden === Abilities.NONE) && tries < 5) { - species = getPokemonSpecies(getRandomSpeciesByStarterTier([0, 5], undefined, undefined, false, false, false)); + species = getPokemonSpecies(getRandomSpeciesByStarterTier([ 0, 5 ], undefined, undefined, false, false, false)); tries++; } diff --git a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts index 4893d95d41b..92f09b1341d 100644 --- a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts @@ -81,42 +81,43 @@ export const TheStrongStuffEncounter: MysteryEncounter = bossSegments: 5, mysteryEncounterPokemonData: new CustomPokemonData({ spriteScale: 1.25 }), nature: Nature.BOLD, - moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER], + moveSet: [ Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER ], modifierConfigs: [ { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ]) as PokemonHeldItemModifierType }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.ENIGMA]) as PokemonHeldItemModifierType + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.ENIGMA ]) as PokemonHeldItemModifierType }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.APICOT]) as PokemonHeldItemModifierType + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.APICOT ]) as PokemonHeldItemModifierType }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.GANLON]) as PokemonHeldItemModifierType + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.GANLON ]) as PokemonHeldItemModifierType }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LUM]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LUM ]) as PokemonHeldItemModifierType, stackCount: 2 } ], - tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { queueEncounterMessage(pokemon.scene, `${namespace}:option.2.stat_boost`); - pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [Stat.DEF, Stat.SPDEF], 2)); + pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ Stat.DEF, Stat.SPDEF ], 2)); } } ], }; - encounter.enemyPartyConfigs = [config]; + encounter.enemyPartyConfigs = [ config ]; - loadCustomMovesForEncounter(scene, [Moves.GASTRO_ACID, Moves.STEALTH_ROCK]); + loadCustomMovesForEncounter(scene, [ Moves.GASTRO_ACID, Moves.STEALTH_ROCK ]); encounter.setDialogueToken("shuckleName", getPokemonSpecies(Species.SHUCKLE).getName()); return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -184,23 +185,23 @@ export const TheStrongStuffEncounter: MysteryEncounter = async (scene: BattleScene) => { // Pick battle const encounter = scene.currentBattle.mysteryEncounter!; - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.SOUL_DEW], fillRemaining: true }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.SOUL_DEW ], fillRemaining: true }); encounter.startOfBattleEffects.push( { sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.PLAYER], + targets: [ BattlerIndex.PLAYER ], move: new PokemonMove(Moves.GASTRO_ACID), ignorePp: true }, { sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.PLAYER], + targets: [ BattlerIndex.PLAYER ], move: new PokemonMove(Moves.STEALTH_ROCK), ignorePp: true }); encounter.dialogue.outro = []; - transitionMysteryEncounterIntroVisuals(scene, true, true, 500); + await transitionMysteryEncounterIntroVisuals(scene, true, true, 500); await initBattleWithEnemyConfig(scene, encounter.enemyPartyConfigs[0]); } ) diff --git a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts index 9e813800b59..bf322802f81 100644 --- a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts @@ -94,6 +94,7 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter = return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -110,8 +111,8 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter = }, async (scene: BattleScene) => { // Spawn 5 trainer battles back to back with Macho Brace in rewards - scene.currentBattle.mysteryEncounter!.doContinueEncounter = (scene: BattleScene) => { - return endTrainerBattleAndShowDialogue(scene); + scene.currentBattle.mysteryEncounter!.doContinueEncounter = async (scene: BattleScene) => { + await endTrainerBattleAndShowDialogue(scene); }; await transitionMysteryEncounterIntroVisuals(scene, true, false); await spawnNextTrainerOrEndEncounter(scene); @@ -131,7 +132,7 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter = async (scene: BattleScene) => { // Refuse the challenge, they full heal the party and give the player a Rarer Candy scene.unshiftPhase(new PartyHealPhase(scene, true)); - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.RARER_CANDY], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.RARER_CANDY ], fillRemaining: false }); leaveEncounterWithoutBattle(scene); } ) @@ -154,7 +155,7 @@ async function spawnNextTrainerOrEndEncounter(scene: BattleScene) { scene.ui.clearText(); // Clears "Winstrate" title from screen as rewards get animated in const machoBrace = generateModifierTypeOption(scene, modifierTypes.MYSTERY_ENCOUNTER_MACHO_BRACE)!; machoBrace.type.tier = ModifierTier.MASTER; - setEncounterRewards(scene, { guaranteedModifierTypeOptions: [machoBrace], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeOptions: [ machoBrace ], fillRemaining: false }); encounter.doContinueEncounter = undefined; leaveEncounterWithoutBattle(scene, false, MysteryEncounterMode.NO_BATTLE); } else { @@ -232,7 +233,7 @@ function getVictorTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, abilityIndex: 0, // Guts nature: Nature.ADAMANT, - moveSet: [Moves.FACADE, Moves.BRAVE_BIRD, Moves.PROTECT, Moves.QUICK_ATTACK], + moveSet: [ Moves.FACADE, Moves.BRAVE_BIRD, Moves.PROTECT, Moves.QUICK_ATTACK ], modifierConfigs: [ { modifier: generateModifierType(scene, modifierTypes.FLAME_ORB) as PokemonHeldItemModifierType, @@ -250,7 +251,7 @@ function getVictorTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, abilityIndex: 1, // Guts nature: Nature.ADAMANT, - moveSet: [Moves.FACADE, Moves.OBSTRUCT, Moves.NIGHT_SLASH, Moves.FIRE_PUNCH], + moveSet: [ Moves.FACADE, Moves.OBSTRUCT, Moves.NIGHT_SLASH, Moves.FIRE_PUNCH ], modifierConfigs: [ { modifier: generateModifierType(scene, modifierTypes.FLAME_ORB) as PokemonHeldItemModifierType, @@ -276,7 +277,7 @@ function getVictoriaTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, abilityIndex: 0, // Natural Cure nature: Nature.CALM, - moveSet: [Moves.SYNTHESIS, Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.SLEEP_POWDER], + moveSet: [ Moves.SYNTHESIS, Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.SLEEP_POWDER ], modifierConfigs: [ { modifier: generateModifierType(scene, modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType, @@ -294,15 +295,15 @@ function getVictoriaTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, formIndex: 1, nature: Nature.TIMID, - moveSet: [Moves.PSYSHOCK, Moves.MOONBLAST, Moves.SHADOW_BALL, Moves.WILL_O_WISP], + moveSet: [ Moves.PSYSHOCK, Moves.MOONBLAST, Moves.SHADOW_BALL, Moves.WILL_O_WISP ], modifierConfigs: [ { - modifier: generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.PSYCHIC]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.PSYCHIC ]) as PokemonHeldItemModifierType, stackCount: 1, isTransferable: false }, { - modifier: generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [Type.FAIRY]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.ATTACK_TYPE_BOOSTER, [ Type.FAIRY ]) as PokemonHeldItemModifierType, stackCount: 1, isTransferable: false } @@ -321,15 +322,15 @@ function getViviTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, abilityIndex: 3, // Lightning Rod nature: Nature.ADAMANT, - moveSet: [Moves.WATERFALL, Moves.MEGAHORN, Moves.KNOCK_OFF, Moves.REST], + moveSet: [ Moves.WATERFALL, Moves.MEGAHORN, Moves.KNOCK_OFF, Moves.REST ], modifierConfigs: [ { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LUM]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LUM ]) as PokemonHeldItemModifierType, stackCount: 2, isTransferable: false }, { - modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [Stat.HP]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [ Stat.HP ]) as PokemonHeldItemModifierType, stackCount: 4, isTransferable: false } @@ -340,10 +341,10 @@ function getViviTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, abilityIndex: 1, // Poison Heal nature: Nature.JOLLY, - moveSet: [Moves.SPORE, Moves.SWORDS_DANCE, Moves.SEED_BOMB, Moves.DRAIN_PUNCH], + moveSet: [ Moves.SPORE, Moves.SWORDS_DANCE, Moves.SEED_BOMB, Moves.DRAIN_PUNCH ], modifierConfigs: [ { - modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [Stat.HP]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [ Stat.HP ]) as PokemonHeldItemModifierType, stackCount: 4, isTransferable: false }, @@ -358,7 +359,7 @@ function getViviTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, formIndex: 1, nature: Nature.CALM, - moveSet: [Moves.EARTH_POWER, Moves.FIRE_BLAST, Moves.YAWN, Moves.PROTECT], + moveSet: [ Moves.EARTH_POWER, Moves.FIRE_BLAST, Moves.YAWN, Moves.PROTECT ], modifierConfigs: [ { modifier: generateModifierType(scene, modifierTypes.QUICK_CLAW) as PokemonHeldItemModifierType, @@ -380,7 +381,7 @@ function getVickyTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, formIndex: 1, nature: Nature.IMPISH, - moveSet: [Moves.AXE_KICK, Moves.ICE_PUNCH, Moves.ZEN_HEADBUTT, Moves.BULLET_PUNCH], + moveSet: [ Moves.AXE_KICK, Moves.ICE_PUNCH, Moves.ZEN_HEADBUTT, Moves.BULLET_PUNCH ], modifierConfigs: [ { modifier: generateModifierType(scene, modifierTypes.SHELL_BELL) as PokemonHeldItemModifierType, @@ -401,10 +402,10 @@ function getVitoTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, abilityIndex: 0, // Soundproof nature: Nature.MODEST, - moveSet: [Moves.THUNDERBOLT, Moves.GIGA_DRAIN, Moves.FOUL_PLAY, Moves.THUNDER_WAVE], + moveSet: [ Moves.THUNDERBOLT, Moves.GIGA_DRAIN, Moves.FOUL_PLAY, Moves.THUNDER_WAVE ], modifierConfigs: [ { - modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [Stat.SPD]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BASE_STAT_BOOSTER, [ Stat.SPD ]) as PokemonHeldItemModifierType, stackCount: 2, isTransferable: false } @@ -415,50 +416,50 @@ function getVitoTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, abilityIndex: 2, // Gluttony nature: Nature.QUIET, - moveSet: [Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.ICE_BEAM, Moves.EARTHQUAKE], + moveSet: [ Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.ICE_BEAM, Moves.EARTHQUAKE ], modifierConfigs: [ { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ]) as PokemonHeldItemModifierType, stackCount: 2, }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.APICOT]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.APICOT ]) as PokemonHeldItemModifierType, stackCount: 2, }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.GANLON]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.GANLON ]) as PokemonHeldItemModifierType, stackCount: 2, }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.STARF]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.STARF ]) as PokemonHeldItemModifierType, stackCount: 2, }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.SALAC]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SALAC ]) as PokemonHeldItemModifierType, stackCount: 2, }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LUM]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LUM ]) as PokemonHeldItemModifierType, stackCount: 2, }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LANSAT]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LANSAT ]) as PokemonHeldItemModifierType, stackCount: 2, }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LIECHI]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LIECHI ]) as PokemonHeldItemModifierType, stackCount: 2, }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.PETAYA]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.PETAYA ]) as PokemonHeldItemModifierType, stackCount: 2, }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.ENIGMA]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.ENIGMA ]) as PokemonHeldItemModifierType, stackCount: 2, }, { - modifier: generateModifierType(scene, modifierTypes.BERRY, [BerryType.LEPPA]) as PokemonHeldItemModifierType, + modifier: generateModifierType(scene, modifierTypes.BERRY, [ BerryType.LEPPA ]) as PokemonHeldItemModifierType, stackCount: 2, } ] @@ -468,7 +469,7 @@ function getVitoTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, abilityIndex: 2, // Tangled Feet nature: Nature.JOLLY, - moveSet: [Moves.DRILL_PECK, Moves.QUICK_ATTACK, Moves.THRASH, Moves.KNOCK_OFF], + moveSet: [ Moves.DRILL_PECK, Moves.QUICK_ATTACK, Moves.THRASH, Moves.KNOCK_OFF ], modifierConfigs: [ { modifier: generateModifierType(scene, modifierTypes.KINGS_ROCK) as PokemonHeldItemModifierType, @@ -482,7 +483,7 @@ function getVitoTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, formIndex: 1, nature: Nature.BOLD, - moveSet: [Moves.PSYCHIC, Moves.SHADOW_BALL, Moves.FOCUS_BLAST, Moves.THUNDERBOLT], + moveSet: [ Moves.PSYCHIC, Moves.SHADOW_BALL, Moves.FOCUS_BLAST, Moves.THUNDERBOLT ], modifierConfigs: [ { modifier: generateModifierType(scene, modifierTypes.WIDE_LENS) as PokemonHeldItemModifierType, @@ -496,7 +497,7 @@ function getVitoTrainerConfig(scene: BattleScene): EnemyPartyConfig { isBoss: false, abilityIndex: 0, // Sheer Force nature: Nature.IMPISH, - moveSet: [Moves.EARTHQUAKE, Moves.U_TURN, Moves.FLARE_BLITZ, Moves.ROCK_SLIDE], + moveSet: [ Moves.EARTHQUAKE, Moves.U_TURN, Moves.FLARE_BLITZ, Moves.ROCK_SLIDE ], modifierConfigs: [ { modifier: generateModifierType(scene, modifierTypes.QUICK_CLAW) as PokemonHeldItemModifierType, diff --git a/src/data/mystery-encounters/encounters/training-session-encounter.ts b/src/data/mystery-encounters/encounters/training-session-encounter.ts index ff993f339cb..9f80bbbffde 100644 --- a/src/data/mystery-encounters/encounters/training-session-encounter.ts +++ b/src/data/mystery-encounters/encounters/training-session-encounter.ts @@ -52,6 +52,7 @@ export const TrainingSessionEncounter: MysteryEncounter = text: `${namespace}:intro`, } ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -161,7 +162,7 @@ export const TrainingSessionEncounter: MysteryEncounter = setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase); - return initBattleWithEnemyConfig(scene, config); + await initBattleWithEnemyConfig(scene, config); }) .build() ) @@ -237,7 +238,7 @@ export const TrainingSessionEncounter: MysteryEncounter = setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase); - return initBattleWithEnemyConfig(scene, config); + await initBattleWithEnemyConfig(scene, config); }) .build() ) @@ -350,7 +351,7 @@ export const TrainingSessionEncounter: MysteryEncounter = setEncounterRewards(scene, { fillRemaining: true }, undefined, onBeforeRewardsPhase); - return initBattleWithEnemyConfig(scene, config); + await initBattleWithEnemyConfig(scene, config); }) .build() ) diff --git a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts index bbf52b0c118..d3c16ce2122 100644 --- a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts +++ b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts @@ -54,6 +54,7 @@ export const TrashToTreasureEncounter: MysteryEncounter = text: `${namespace}:intro`, }, ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -67,17 +68,17 @@ export const TrashToTreasureEncounter: MysteryEncounter = isBoss: true, formIndex: 1, // Gmax bossSegmentModifier: 1, // +1 Segment from normal - moveSet: [Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH] + moveSet: [ Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH ] }; const config: EnemyPartyConfig = { levelAdditiveModifier: 0.5, - pokemonConfigs: [pokemonConfig], + pokemonConfigs: [ pokemonConfig ], disableSwitch: true }; - encounter.enemyPartyConfigs = [config]; + encounter.enemyPartyConfigs = [ config ]; // Load animations/sfx for Garbodor fight start moves - loadCustomMovesForEncounter(scene, [Moves.TOXIC, Moves.AMNESIA]); + loadCustomMovesForEncounter(scene, [ Moves.TOXIC, Moves.AMNESIA ]); scene.loadSe("PRSFX- Dig2", "battle_anims", "PRSFX- Dig2.wav"); scene.loadSe("PRSFX- Venom Drench", "battle_anims", "PRSFX- Venom Drench.wav"); @@ -104,10 +105,10 @@ export const TrashToTreasureEncounter: MysteryEncounter = }) .withOptionPhase(async (scene: BattleScene) => { // Gain 2 Leftovers and 2 Shell Bell - transitionMysteryEncounterIntroVisuals(scene); + await transitionMysteryEncounterIntroVisuals(scene); await tryApplyDigRewardItems(scene); - const blackSludge = generateModifierType(scene, modifierTypes.MYSTERY_ENCOUNTER_BLACK_SLUDGE, [SHOP_ITEM_COST_MULTIPLIER]); + const blackSludge = generateModifierType(scene, modifierTypes.MYSTERY_ENCOUNTER_BLACK_SLUDGE, [ SHOP_ITEM_COST_MULTIPLIER ]); const modifier = blackSludge?.newModifier(); if (modifier) { await scene.addModifier(modifier, false, false, false, true); @@ -135,21 +136,21 @@ export const TrashToTreasureEncounter: MysteryEncounter = // Investigate garbage, battle Gmax Garbodor scene.setFieldScale(0.75); await showEncounterText(scene, `${namespace}:option.2.selected_2`); - transitionMysteryEncounterIntroVisuals(scene); + await transitionMysteryEncounterIntroVisuals(scene); const encounter = scene.currentBattle.mysteryEncounter!; - setEncounterRewards(scene, { guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT], fillRemaining: true }); + setEncounterRewards(scene, { guaranteedModifierTiers: [ ModifierTier.ROGUE, ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT ], fillRemaining: true }); encounter.startOfBattleEffects.push( { sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.PLAYER], + targets: [ BattlerIndex.PLAYER ], move: new PokemonMove(Moves.TOXIC), ignorePp: true }, { sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.ENEMY], + targets: [ BattlerIndex.ENEMY ], move: new PokemonMove(Moves.AMNESIA), ignorePp: true }); @@ -221,7 +222,7 @@ async function tryApplyDigRewardItems(scene: BattleScene) { await showEncounterText(scene, i18next.t("battle:rewardGainCount", { modifierName: shellBell.name, count: 2 }), null, undefined, true); } -async function doGarbageDig(scene: BattleScene) { +function doGarbageDig(scene: BattleScene) { scene.playSound("battle_anims/PRSFX- Dig2"); scene.time.delayedCall(SOUND_EFFECT_WAIT_TIME, () => { scene.playSound("battle_anims/PRSFX- Dig2"); diff --git a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts index d06720400c2..13594f273d9 100644 --- a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts +++ b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts @@ -74,8 +74,8 @@ export const UncommonBreedEncounter: MysteryEncounter = // Defense/Spd buffs below wave 50, +1 to all stats otherwise const statChangesForBattle: (Stat.ATK | Stat.DEF | Stat.SPATK | Stat.SPDEF | Stat.SPD | Stat.ACC | Stat.EVA)[] = scene.currentBattle.waveIndex < 50 ? - [Stat.DEF, Stat.SPDEF, Stat.SPD] : - [Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD]; + [ Stat.DEF, Stat.SPDEF, Stat.SPD ] : + [ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ]; const config: EnemyPartyConfig = { pokemonConfigs: [{ @@ -83,14 +83,14 @@ export const UncommonBreedEncounter: MysteryEncounter = species: species, dataSource: new PokemonData(pokemon), isBoss: false, - tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { queueEncounterMessage(pokemon.scene, `${namespace}:option.1.stat_boost`); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, statChangesForBattle, 1)); } }], }; - encounter.enemyPartyConfigs = [config]; + encounter.enemyPartyConfigs = [ config ]; const { spriteKey, fileRoot } = getSpriteKeysFromPokemon(pokemon); encounter.spriteConfigs = [ @@ -125,6 +125,7 @@ export const UncommonBreedEncounter: MysteryEncounter = scene.time.delayedCall(500, () => scene.playSound("battle_anims/PRSFX- Spotlight2")); return true; }) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -152,7 +153,7 @@ export const UncommonBreedEncounter: MysteryEncounter = encounter.startOfBattleEffects.push( { sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [target], + targets: [ target ], move: pokemonMove, ignorePp: true }); @@ -181,7 +182,7 @@ export const UncommonBreedEncounter: MysteryEncounter = // Remove 4 random berries from player's party // Get all player berry items, remove from party, and store reference - const berryItems: BerryModifier[]= scene.findModifiers(m => m instanceof BerryModifier) as BerryModifier[]; + const berryItems: BerryModifier[] = scene.findModifiers(m => m instanceof BerryModifier) as BerryModifier[]; for (let i = 0; i < 4; i++) { const index = randSeedInt(berryItems.length); const randBerry = berryItems[index]; diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index 4842ec0a0ce..e1e5444eaa7 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -96,12 +96,12 @@ const PERCENT_LEVEL_LOSS_ON_REFUSE = 10; * Value ranges of the resulting species BST transformations after adding values to original species * 2 Pokemon in the party use this range */ -const HIGH_BST_TRANSFORM_BASE_VALUES: [number, number] = [90, 110]; +const HIGH_BST_TRANSFORM_BASE_VALUES: [number, number] = [ 90, 110 ]; /** * Value ranges of the resulting species BST transformations after adding values to original species * All remaining Pokemon in the party use this range */ -const STANDARD_BST_TRANSFORM_BASE_VALUES: [number, number] = [40, 50]; +const STANDARD_BST_TRANSFORM_BASE_VALUES: [number, number] = [ 40, 50 ]; /** * Weird Dream encounter. @@ -133,6 +133,7 @@ export const WeirdDreamEncounter: MysteryEncounter = text: `${namespace}:intro_dialogue`, }, ]) + .setLocalizationKey(`${namespace}`) .withTitle(`${namespace}:title`) .withDescription(`${namespace}:description`) .withQuery(`${namespace}:query`) @@ -206,7 +207,7 @@ export const WeirdDreamEncounter: MysteryEncounter = await showEncounterText(scene, `${namespace}:option.1.dream_complete`); await doNewTeamPostProcess(scene, transformations); - setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [modifierTypes.MEMORY_MUSHROOM, modifierTypes.ROGUE_BALL, modifierTypes.MINT, modifierTypes.MINT, modifierTypes.MINT], fillRemaining: false }); + setEncounterRewards(scene, { guaranteedModifierTypeFuncs: [ modifierTypes.MEMORY_MUSHROOM, modifierTypes.ROGUE_BALL, modifierTypes.MINT, modifierTypes.MINT, modifierTypes.MINT ], fillRemaining: false }); leaveEncounterWithoutBattle(scene, true); }) .build() @@ -671,7 +672,7 @@ async function addEggMoveToNewPokemonMoveset(scene: BattleScene, newPokemon: Pla let eggMoveIndex: null | number = null; const eggMoves = newPokemon.getEggMoves()?.slice(0); if (eggMoves) { - const eggMoveIndices = randSeedShuffle([0, 1, 2, 3]); + const eggMoveIndices = randSeedShuffle([ 0, 1, 2, 3 ]); let randomEggMoveIndex = eggMoveIndices.pop(); let randomEggMove = !isNullOrUndefined(randomEggMoveIndex) ? eggMoves[randomEggMoveIndex] : null; let retries = 0; diff --git a/src/data/mystery-encounters/mystery-encounter-requirements.ts b/src/data/mystery-encounters/mystery-encounter-requirements.ts index f6f577b8d4e..5cb2673df22 100644 --- a/src/data/mystery-encounters/mystery-encounter-requirements.ts +++ b/src/data/mystery-encounters/mystery-encounter-requirements.ts @@ -147,7 +147,7 @@ export class PreviousEncounterRequirement extends EncounterSceneRequirement { } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { - return ["previousEncounter", scene.mysteryEncounterSaveData.encounteredEvents.find(e => e.type === this.previousEncounterRequirement)?.[0].toString() ?? ""]; + return [ "previousEncounter", scene.mysteryEncounterSaveData.encounteredEvents.find(e => e.type === this.previousEncounterRequirement)?.[0].toString() ?? "" ]; } } @@ -175,7 +175,7 @@ export class WaveRangeRequirement extends EncounterSceneRequirement { } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { - return ["waveIndex", scene.currentBattle.waveIndex.toString()]; + return [ "waveIndex", scene.currentBattle.waveIndex.toString() ]; } } @@ -204,7 +204,7 @@ export class WaveModulusRequirement extends EncounterSceneRequirement { } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { - return ["waveIndex", scene.currentBattle.waveIndex.toString()]; + return [ "waveIndex", scene.currentBattle.waveIndex.toString() ]; } } @@ -213,7 +213,7 @@ export class TimeOfDayRequirement extends EncounterSceneRequirement { constructor(timeOfDay: TimeOfDay | TimeOfDay[]) { super(); - this.requiredTimeOfDay = Array.isArray(timeOfDay) ? timeOfDay : [timeOfDay]; + this.requiredTimeOfDay = Array.isArray(timeOfDay) ? timeOfDay : [ timeOfDay ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -226,7 +226,7 @@ export class TimeOfDayRequirement extends EncounterSceneRequirement { } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { - return ["timeOfDay", TimeOfDay[scene.arena.getTimeOfDay()].toLocaleLowerCase()]; + return [ "timeOfDay", TimeOfDay[scene.arena.getTimeOfDay()].toLocaleLowerCase() ]; } } @@ -235,7 +235,7 @@ export class WeatherRequirement extends EncounterSceneRequirement { constructor(weather: WeatherType | WeatherType[]) { super(); - this.requiredWeather = Array.isArray(weather) ? weather : [weather]; + this.requiredWeather = Array.isArray(weather) ? weather : [ weather ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -253,7 +253,7 @@ export class WeatherRequirement extends EncounterSceneRequirement { if (!isNullOrUndefined(currentWeather)) { token = WeatherType[currentWeather].replace("_", " ").toLocaleLowerCase(); } - return ["weather", token]; + return [ "weather", token ]; } } @@ -285,7 +285,7 @@ export class PartySizeRequirement extends EncounterSceneRequirement { } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { - return ["partySize", scene.getParty().length.toString()]; + return [ "partySize", scene.getParty().length.toString() ]; } } @@ -296,7 +296,7 @@ export class PersistentModifierRequirement extends EncounterSceneRequirement { constructor(heldItem: string | string[], minNumberOfItems: number = 1) { super(); this.minNumberOfItems = minNumberOfItems; - this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [heldItem]; + this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [ heldItem ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -318,7 +318,7 @@ export class PersistentModifierRequirement extends EncounterSceneRequirement { } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { - return ["requiredItem", this.requiredHeldItemModifiers[0]]; + return [ "requiredItem", this.requiredHeldItemModifiers[0] ]; } } @@ -346,7 +346,7 @@ export class MoneyRequirement extends EncounterSceneRequirement { override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { const value = this.scalingMultiplier > 0 ? scene.getWaveMoneyAmount(this.scalingMultiplier).toString() : this.requiredMoney.toString(); - return ["money", value]; + return [ "money", value ]; } } @@ -359,7 +359,7 @@ export class SpeciesRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredSpecies = Array.isArray(species) ? species : [species]; + this.requiredSpecies = Array.isArray(species) ? species : [ species ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -381,9 +381,9 @@ export class SpeciesRequirement extends EncounterPokemonRequirement { override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { if (pokemon?.species.speciesId && this.requiredSpecies.includes(pokemon.species.speciesId)) { - return ["species", Species[pokemon.species.speciesId]]; + return [ "species", Species[pokemon.species.speciesId] ]; } - return ["species", ""]; + return [ "species", "" ]; } } @@ -397,7 +397,7 @@ export class NatureRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredNature = Array.isArray(nature) ? nature : [nature]; + this.requiredNature = Array.isArray(nature) ? nature : [ nature ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -419,9 +419,9 @@ export class NatureRequirement extends EncounterPokemonRequirement { override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { if (!isNullOrUndefined(pokemon?.nature) && this.requiredNature.includes(pokemon.nature)) { - return ["nature", Nature[pokemon.nature]]; + return [ "nature", Nature[pokemon.nature] ]; } - return ["nature", ""]; + return [ "nature", "" ]; } } @@ -436,7 +436,7 @@ export class TypeRequirement extends EncounterPokemonRequirement { this.excludeFainted = excludeFainted; this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredType = Array.isArray(type) ? type : [type]; + this.requiredType = Array.isArray(type) ? type : [ type ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -465,9 +465,9 @@ export class TypeRequirement extends EncounterPokemonRequirement { override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { const includedTypes = this.requiredType.filter((ty) => pokemon?.getTypes().includes(ty)); if (includedTypes.length > 0) { - return ["type", Type[includedTypes[0]]]; + return [ "type", Type[includedTypes[0]] ]; } - return ["type", ""]; + return [ "type", "" ]; } } @@ -481,7 +481,7 @@ export class MoveRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredMoves = Array.isArray(moves) ? moves : [moves]; + this.requiredMoves = Array.isArray(moves) ? moves : [ moves ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -504,9 +504,9 @@ export class MoveRequirement extends EncounterPokemonRequirement { override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { const includedMoves = pokemon?.moveset.filter((move) => move?.moveId && this.requiredMoves.includes(move.moveId)); if (includedMoves && includedMoves.length > 0 && includedMoves[0]) { - return ["move", includedMoves[0].getName()]; + return [ "move", includedMoves[0].getName() ]; } - return ["move", ""]; + return [ "move", "" ]; } } @@ -525,7 +525,7 @@ export class CompatibleMoveRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredMoves = Array.isArray(learnableMove) ? learnableMove : [learnableMove]; + this.requiredMoves = Array.isArray(learnableMove) ? learnableMove : [ learnableMove ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -548,9 +548,9 @@ export class CompatibleMoveRequirement extends EncounterPokemonRequirement { override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { const includedCompatMoves = this.requiredMoves.filter((reqMove) => pokemon?.compatibleTms.filter((tm) => !pokemon.moveset.find(m => m?.moveId === tm)).includes(reqMove)); if (includedCompatMoves.length > 0) { - return ["compatibleMove", Moves[includedCompatMoves[0]]]; + return [ "compatibleMove", Moves[includedCompatMoves[0]] ]; } - return ["compatibleMove", ""]; + return [ "compatibleMove", "" ]; } } @@ -564,7 +564,7 @@ export class AbilityRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredAbilities = Array.isArray(abilities) ? abilities : [abilities]; + this.requiredAbilities = Array.isArray(abilities) ? abilities : [ abilities ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -586,9 +586,9 @@ export class AbilityRequirement extends EncounterPokemonRequirement { override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { if (pokemon?.getAbility().id && this.requiredAbilities.some(a => pokemon.getAbility().id === a)) { - return ["ability", pokemon.getAbility().name]; + return [ "ability", pokemon.getAbility().name ]; } - return ["ability", ""]; + return [ "ability", "" ]; } } @@ -601,7 +601,7 @@ export class StatusEffectRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredStatusEffect = Array.isArray(statusEffect) ? statusEffect : [statusEffect]; + this.requiredStatusEffect = Array.isArray(statusEffect) ? statusEffect : [ statusEffect ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -649,9 +649,9 @@ export class StatusEffectRequirement extends EncounterPokemonRequirement { return pokemon!.status?.effect === a; }); if (reqStatus.length > 0) { - return ["status", StatusEffect[reqStatus[0]]]; + return [ "status", StatusEffect[reqStatus[0]] ]; } - return ["status", ""]; + return [ "status", "" ]; } } @@ -670,7 +670,7 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredFormChangeItem = Array.isArray(formChangeItem) ? formChangeItem : [formChangeItem]; + this.requiredFormChangeItem = Array.isArray(formChangeItem) ? formChangeItem : [ formChangeItem ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -706,9 +706,9 @@ export class CanFormChangeWithItemRequirement extends EncounterPokemonRequiremen override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { const requiredItems = this.requiredFormChangeItem.filter((formChangeItem) => this.filterByForm(pokemon, formChangeItem)); if (requiredItems.length > 0) { - return ["formChangeItem", FormChangeItem[requiredItems[0]]]; + return [ "formChangeItem", FormChangeItem[requiredItems[0]] ]; } - return ["formChangeItem", ""]; + return [ "formChangeItem", "" ]; } } @@ -722,7 +722,7 @@ export class CanEvolveWithItemRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredEvolutionItem = Array.isArray(evolutionItems) ? evolutionItems : [evolutionItems]; + this.requiredEvolutionItem = Array.isArray(evolutionItems) ? evolutionItems : [ evolutionItems ]; } override meetsRequirement(scene: BattleScene): boolean { @@ -756,9 +756,9 @@ export class CanEvolveWithItemRequirement extends EncounterPokemonRequirement { override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { const requiredItems = this.requiredEvolutionItem.filter((evoItem) => this.filterByEvo(pokemon, evoItem)); if (requiredItems.length > 0) { - return ["evolutionItem", EvolutionItem[requiredItems[0]]]; + return [ "evolutionItem", EvolutionItem[requiredItems[0]] ]; } - return ["evolutionItem", ""]; + return [ "evolutionItem", "" ]; } } @@ -772,7 +772,7 @@ export class HeldItemRequirement extends EncounterPokemonRequirement { super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [heldItem]; + this.requiredHeldItemModifiers = Array.isArray(heldItem) ? heldItem : [ heldItem ]; this.requireTransferable = requireTransferable; } @@ -807,9 +807,9 @@ export class HeldItemRequirement extends EncounterPokemonRequirement { && (!this.requireTransferable || it.isTransferable); }); if (requiredItems && requiredItems.length > 0) { - return ["heldItem", requiredItems[0].type.name]; + return [ "heldItem", requiredItems[0].type.name ]; } - return ["heldItem", ""]; + return [ "heldItem", "" ]; } } @@ -823,7 +823,7 @@ export class AttackTypeBoosterHeldItemTypeRequirement extends EncounterPokemonRe super(); this.minNumberOfPokemon = minNumberOfPokemon; this.invertQuery = invertQuery; - this.requiredHeldItemTypes = Array.isArray(heldItemTypes) ? heldItemTypes : [heldItemTypes]; + this.requiredHeldItemTypes = Array.isArray(heldItemTypes) ? heldItemTypes : [ heldItemTypes ]; this.requireTransferable = requireTransferable; } @@ -864,9 +864,9 @@ export class AttackTypeBoosterHeldItemTypeRequirement extends EncounterPokemonRe && (!this.requireTransferable || it.isTransferable); }); if (requiredItems && requiredItems.length > 0) { - return ["heldItem", requiredItems[0].type.name]; + return [ "heldItem", requiredItems[0].type.name ]; } - return ["heldItem", ""]; + return [ "heldItem", "" ]; } } @@ -904,7 +904,7 @@ export class LevelRequirement extends EncounterPokemonRequirement { } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { - return ["level", pokemon?.level.toString() ?? ""]; + return [ "level", pokemon?.level.toString() ?? "" ]; } } @@ -942,7 +942,7 @@ export class FriendshipRequirement extends EncounterPokemonRequirement { } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { - return ["friendship", pokemon?.friendship.toString() ?? ""]; + return [ "friendship", pokemon?.friendship.toString() ?? "" ]; } } @@ -989,9 +989,9 @@ export class HealthRatioRequirement extends EncounterPokemonRequirement { override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { const hpRatio = pokemon?.getHpRatio(); if (!isNullOrUndefined(hpRatio)) { - return ["healthRatio", Math.floor(hpRatio * 100).toString() + "%"]; + return [ "healthRatio", Math.floor(hpRatio * 100).toString() + "%" ]; } - return ["healthRatio", ""]; + return [ "healthRatio", "" ]; } } @@ -1029,8 +1029,7 @@ export class WeightRequirement extends EncounterPokemonRequirement { } override getDialogueToken(scene: BattleScene, pokemon?: PlayerPokemon): [string, string] { - return ["weight", pokemon?.getWeight().toString() ?? ""]; + return [ "weight", pokemon?.getWeight().toString() ?? "" ]; } } - diff --git a/src/data/mystery-encounters/mystery-encounter.ts b/src/data/mystery-encounters/mystery-encounter.ts index da4d29c94d6..7e175957e21 100644 --- a/src/data/mystery-encounters/mystery-encounter.ts +++ b/src/data/mystery-encounters/mystery-encounter.ts @@ -190,7 +190,7 @@ export default class MysteryEncounter implements IMysteryEncounter { secondaryPokemon?: PlayerPokemon[]; // #region Post-construct / Auto-populated params - + localizationKey: string; /** * Dialogue object containing all the dialogue, messages, tooltips, etc. for an encounter */ @@ -264,8 +264,9 @@ export default class MysteryEncounter implements IMysteryEncounter { Object.assign(this, encounter); } this.encounterTier = this.encounterTier ?? MysteryEncounterTier.COMMON; + this.localizationKey = this.localizationKey ?? ""; this.dialogue = this.dialogue ?? {}; - this.spriteConfigs = this.spriteConfigs ? [...this.spriteConfigs] : []; + this.spriteConfigs = this.spriteConfigs ? [ ...this.spriteConfigs ] : []; // Default max is 1 for ROGUE encounters, 2 for others this.maxAllowedEncounters = this.maxAllowedEncounters ?? this.encounterTier === MysteryEncounterTier.ROGUE ? DEFAULT_MAX_ALLOWED_ROGUE_ENCOUNTERS : DEFAULT_MAX_ALLOWED_ENCOUNTERS; this.encounterMode = MysteryEncounterMode.DEFAULT; @@ -528,6 +529,7 @@ export class MysteryEncounterBuilder implements Partial { options: [MysteryEncounterOption, MysteryEncounterOption, ...MysteryEncounterOption[]]; enemyPartyConfigs: EnemyPartyConfig[] = []; + localizationKey: string = ""; dialogue: MysteryEncounterDialogue = {}; requirements: EncounterSceneRequirement[] = []; primaryPokemonRequirements: EncounterPokemonRequirement[] = []; @@ -573,7 +575,7 @@ export class MysteryEncounterBuilder implements Partial { */ withOption(option: MysteryEncounterOption): this & Pick { if (!this.options) { - const options = [option]; + const options = [ option ]; return Object.assign(this, { options }); } else { this.options.push(option); @@ -624,14 +626,24 @@ export class MysteryEncounterBuilder implements Partial { } withIntroDialogue(dialogue: MysteryEncounterDialogue["intro"] = []): this { - this.dialogue = {...this.dialogue, intro: dialogue }; + this.dialogue = { ...this.dialogue, intro: dialogue }; return this; } - withIntro({spriteConfigs, dialogue} : {spriteConfigs: MysteryEncounterSpriteConfig[], dialogue?: MysteryEncounterDialogue["intro"]}) { + withIntro({ spriteConfigs, dialogue } : {spriteConfigs: MysteryEncounterSpriteConfig[], dialogue?: MysteryEncounterDialogue["intro"]}) { return this.withIntroSpriteConfigs(spriteConfigs).withIntroDialogue(dialogue); } + /** + * Sets the localization key used by the encounter + * @param localizationKey the string used as the key + * @returns `this` + */ + setLocalizationKey(localizationKey: string): this { + this.localizationKey = localizationKey; + return this; + } + /** * OPTIONAL */ @@ -660,7 +672,7 @@ export class MysteryEncounterBuilder implements Partial { * @returns */ withAnimations(...encounterAnimations: EncounterAnim[]): this & Required> { - const animations = Array.isArray(encounterAnimations) ? encounterAnimations : [encounterAnimations]; + const animations = Array.isArray(encounterAnimations) ? encounterAnimations : [ encounterAnimations ]; return Object.assign(this, { encounterAnimations: animations }); } @@ -670,7 +682,7 @@ export class MysteryEncounterBuilder implements Partial { * @param disallowedGameModes */ withDisallowedGameModes(...disallowedGameModes: GameModes[]): this & Required> { - const gameModes = Array.isArray(disallowedGameModes) ? disallowedGameModes : [disallowedGameModes]; + const gameModes = Array.isArray(disallowedGameModes) ? disallowedGameModes : [ disallowedGameModes ]; return Object.assign(this, { disallowedGameModes: gameModes }); } @@ -680,7 +692,7 @@ export class MysteryEncounterBuilder implements Partial { * @param disallowedChallenges */ withDisallowedChallenges(...disallowedChallenges: Challenges[]): this & Required> { - const challenges = Array.isArray(disallowedChallenges) ? disallowedChallenges : [disallowedChallenges]; + const challenges = Array.isArray(disallowedChallenges) ? disallowedChallenges : [ disallowedChallenges ]; return Object.assign(this, { disallowedChallenges: challenges }); } @@ -755,7 +767,7 @@ export class MysteryEncounterBuilder implements Partial { * @returns */ withSceneWaveRangeRequirement(min: number, max?: number): this & Required> { - return this.withSceneRequirement(new WaveRangeRequirement([min, max ?? min])); + return this.withSceneRequirement(new WaveRangeRequirement([ min, max ?? min ])); } /** @@ -767,7 +779,7 @@ export class MysteryEncounterBuilder implements Partial { * @returns */ withScenePartySizeRequirement(min: number, max?: number, excludeDisallowedPokemon: boolean = false): this & Required> { - return this.withSceneRequirement(new PartySizeRequirement([min, max ?? min], excludeDisallowedPokemon)); + return this.withSceneRequirement(new PartySizeRequirement([ min, max ?? min ], excludeDisallowedPokemon)); } /** @@ -982,7 +994,7 @@ export class MysteryEncounterBuilder implements Partial { * @returns */ withOutroDialogue(dialogue: MysteryEncounterDialogue["outro"] = []): this { - this.dialogue = {...this.dialogue, outro: dialogue }; + this.dialogue = { ...this.dialogue, outro: dialogue }; return this; } diff --git a/src/data/mystery-encounters/mystery-encounters.ts b/src/data/mystery-encounters/mystery-encounters.ts index 8fde06f3b14..8c1c3bf6de4 100644 --- a/src/data/mystery-encounters/mystery-encounters.ts +++ b/src/data/mystery-encounters/mystery-encounters.ts @@ -224,72 +224,72 @@ const anyBiomeEncounters: MysteryEncounterType[] = [ * that biome groups do not cover */ export const mysteryEncountersByBiome = new Map([ - [Biome.TOWN, []], - [Biome.PLAINS, [ + [ Biome.TOWN, []], + [ Biome.PLAINS, [ MysteryEncounterType.SLUMBERING_SNORLAX, MysteryEncounterType.ABSOLUTE_AVARICE ]], - [Biome.GRASS, [ + [ Biome.GRASS, [ MysteryEncounterType.SLUMBERING_SNORLAX, MysteryEncounterType.ABSOLUTE_AVARICE ]], - [Biome.TALL_GRASS, [ + [ Biome.TALL_GRASS, [ MysteryEncounterType.ABSOLUTE_AVARICE ]], - [Biome.METROPOLIS, []], - [Biome.FOREST, [ + [ Biome.METROPOLIS, []], + [ Biome.FOREST, [ MysteryEncounterType.SAFARI_ZONE, MysteryEncounterType.ABSOLUTE_AVARICE ]], - [Biome.SEA, [ + [ Biome.SEA, [ MysteryEncounterType.LOST_AT_SEA ]], - [Biome.SWAMP, [ + [ Biome.SWAMP, [ MysteryEncounterType.SAFARI_ZONE ]], - [Biome.BEACH, []], - [Biome.LAKE, []], - [Biome.SEABED, []], - [Biome.MOUNTAIN, []], - [Biome.BADLANDS, [ + [ Biome.BEACH, []], + [ Biome.LAKE, []], + [ Biome.SEABED, []], + [ Biome.MOUNTAIN, []], + [ Biome.BADLANDS, [ MysteryEncounterType.DANCING_LESSONS ]], - [Biome.CAVE, [ + [ Biome.CAVE, [ MysteryEncounterType.THE_STRONG_STUFF ]], - [Biome.DESERT, [ + [ Biome.DESERT, [ MysteryEncounterType.DANCING_LESSONS ]], - [Biome.ICE_CAVE, []], - [Biome.MEADOW, []], - [Biome.POWER_PLANT, []], - [Biome.VOLCANO, [ + [ Biome.ICE_CAVE, []], + [ Biome.MEADOW, []], + [ Biome.POWER_PLANT, []], + [ Biome.VOLCANO, [ MysteryEncounterType.FIERY_FALLOUT, MysteryEncounterType.DANCING_LESSONS ]], - [Biome.GRAVEYARD, []], - [Biome.DOJO, []], - [Biome.FACTORY, []], - [Biome.RUINS, []], - [Biome.WASTELAND, [ + [ Biome.GRAVEYARD, []], + [ Biome.DOJO, []], + [ Biome.FACTORY, []], + [ Biome.RUINS, []], + [ Biome.WASTELAND, [ MysteryEncounterType.DANCING_LESSONS ]], - [Biome.ABYSS, [ + [ Biome.ABYSS, [ MysteryEncounterType.DANCING_LESSONS ]], - [Biome.SPACE, [ + [ Biome.SPACE, [ MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER ]], - [Biome.CONSTRUCTION_SITE, []], - [Biome.JUNGLE, [ + [ Biome.CONSTRUCTION_SITE, []], + [ Biome.JUNGLE, [ MysteryEncounterType.SAFARI_ZONE ]], - [Biome.FAIRY_CAVE, []], - [Biome.TEMPLE, []], - [Biome.SLUM, []], - [Biome.SNOWY_FOREST, []], - [Biome.ISLAND, []], - [Biome.LABORATORY, []] + [ Biome.FAIRY_CAVE, []], + [ Biome.TEMPLE, []], + [ Biome.SLUM, []], + [ Biome.SNOWY_FOREST, []], + [ Biome.ISLAND, []], + [ Biome.LABORATORY, []] ]); export function initMysteryEncounters() { diff --git a/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts b/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts index a0b4edd4a36..f34d383dbbc 100644 --- a/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts +++ b/src/data/mystery-encounters/requirements/can-learn-move-requirement.ts @@ -28,7 +28,7 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement { constructor(requiredMoves: Moves | Moves[], options: CanLearnMoveRequirementOptions = {}) { super(); - this.requiredMoves = Array.isArray(requiredMoves) ? requiredMoves : [requiredMoves]; + this.requiredMoves = Array.isArray(requiredMoves) ? requiredMoves : [ requiredMoves ]; this.excludeLevelMoves = options.excludeLevelMoves ?? false; this.excludeTmMoves = options.excludeTmMoves ?? false; @@ -64,11 +64,11 @@ export class CanLearnMoveRequirement extends EncounterPokemonRequirement { } override getDialogueToken(_scene: BattleScene, _pokemon?: PlayerPokemon): [string, string] { - return ["requiredMoves", this.requiredMoves.map(m => new PokemonMove(m).getName()).join(", ")]; + return [ "requiredMoves", this.requiredMoves.map(m => new PokemonMove(m).getName()).join(", ") ]; } private getPokemonLevelMoves(pkm: PlayerPokemon): Moves[] { - return pkm.getLevelMoves().map(([_level, move]) => move); + return pkm.getLevelMoves().map(([ _level, move ]) => move); } private getAllPokemonMoves(pkm: PlayerPokemon): Moves[] { diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index 23713660daa..907399bf516 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -373,7 +373,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig: * @param moves */ export function loadCustomMovesForEncounter(scene: BattleScene, moves: Moves | Moves[]) { - moves = Array.isArray(moves) ? moves : [moves]; + moves = Array.isArray(moves) ? moves : [ moves ]; return Promise.all(moves.map(move => initMoveAnim(scene, move))) .then(() => loadMoveAnimAssets(scene, moves)); } @@ -663,7 +663,7 @@ export function setEncounterRewards(scene: BattleScene, customShopRewards?: Cust * @param useWaveIndex - set to false when directly passing the the full exp value instead of baseExpValue */ export function setEncounterExp(scene: BattleScene, participantId: number | number[], baseExpValue: number, useWaveIndex: boolean = true) { - const participantIds = Array.isArray(participantId) ? participantId : [participantId]; + const participantIds = Array.isArray(participantId) ? participantId : [ participantId ]; scene.currentBattle.mysteryEncounter!.doEncounterExp = (scene: BattleScene) => { scene.unshiftPhase(new PartyExpPhase(scene, baseExpValue, useWaveIndex, new Set(participantIds))); @@ -800,8 +800,8 @@ export function transitionMysteryEncounterIntroVisuals(scene: BattleScene, hide: // Transition scene.tweens.add({ - targets: [introVisuals, enemyPokemon], - x: `${hide? "+" : "-"}=16`, + targets: [ introVisuals, enemyPokemon ], + x: `${hide ? "+" : "-"}=16`, y: `${hide ? "-" : "+"}=16`, alpha: hide ? 0 : 1, ease: "Sine.easeInOut", @@ -888,14 +888,14 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n const numRuns = 1000; let run = 0; const biomes = Object.keys(Biome).filter(key => isNaN(Number(key))); - const alwaysPickTheseBiomes = [Biome.ISLAND, Biome.ABYSS, Biome.WASTELAND, Biome.FAIRY_CAVE, Biome.TEMPLE, Biome.LABORATORY, Biome.SPACE, Biome.WASTELAND]; + const alwaysPickTheseBiomes = [ Biome.ISLAND, Biome.ABYSS, Biome.WASTELAND, Biome.FAIRY_CAVE, Biome.TEMPLE, Biome.LABORATORY, Biome.SPACE, Biome.WASTELAND ]; const calculateNumEncounters = (): any[] => { let encounterRate = baseSpawnWeight; // BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT - const numEncounters = [0, 0, 0, 0]; + const numEncounters = [ 0, 0, 0, 0 ]; let mostRecentEncounterWave = 0; - const encountersByBiome = new Map(biomes.map(b => [b, 0])); - const validMEfloorsByBiome = new Map(biomes.map(b => [b, 0])); + const encountersByBiome = new Map(biomes.map(b => [ b, 0 ])); + const validMEfloorsByBiome = new Map(biomes.map(b => [ b, 0 ])); let currentBiome = Biome.TOWN; let currentArena = scene.newArena(currentBiome); scene.setSeed(Utils.randomString(24)); @@ -968,7 +968,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n // Calculate encounter rarity // Common / Uncommon / Rare / Super Rare (base is out of 128) - const tierWeights = [66, 40, 19, 3]; + const tierWeights = [ 66, 40, 19, 3 ]; // Adjust tier weights by currently encountered events (pity system that lowers odds of multiple Common/Great) tierWeights[0] = tierWeights[0] - 6 * numEncounters[0]; @@ -987,7 +987,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n } } - return [numEncounters, encountersByBiome, validMEfloorsByBiome]; + return [ numEncounters, encountersByBiome, validMEfloorsByBiome ]; }; const encounterRuns: number[][] = []; @@ -995,7 +995,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n const validFloorsByBiome: Map[] = []; while (run < numRuns) { scene.executeWithSeedOffset(() => { - const [numEncounters, encountersByBiome, validMEfloorsByBiome] = calculateNumEncounters(); + const [ numEncounters, encountersByBiome, validMEfloorsByBiome ] = calculateNumEncounters(); encounterRuns.push(numEncounters); encountersByBiomeRuns.push(encountersByBiome); validFloorsByBiome.push(validMEfloorsByBiome); @@ -1036,7 +1036,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n let stats = `Starting weight: ${baseSpawnWeight}\nAverage MEs per run: ${totalMean}\nStandard Deviation: ${totalStd}\nAvg Commons: ${commonMean}\nAvg Greats: ${uncommonMean}\nAvg Ultras: ${rareMean}\nAvg Rogues: ${superRareMean}\n`; - const meanEncountersPerRunPerBiomeSorted = [...meanEncountersPerRunPerBiome.entries()].sort((e1, e2) => e2[1] - e1[1]); + const meanEncountersPerRunPerBiomeSorted = [ ...meanEncountersPerRunPerBiome.entries() ].sort((e1, e2) => e2[1] - e1[1]); meanEncountersPerRunPerBiomeSorted.forEach(value => stats = stats + `${value[0]}: avg valid floors ${meanMEFloorsPerRunPerBiome.get(value[0])}, avg MEs ${value[1]},\n`); console.log(stats); @@ -1054,7 +1054,7 @@ export function calculateRareSpawnAggregateStats(scene: BattleScene, luckValue: let run = 0; const calculateNumRareEncounters = (): any[] => { - const bossEncountersByRarity = [0, 0, 0, 0]; + const bossEncountersByRarity = [ 0, 0, 0, 0 ]; scene.setSeed(Utils.randomString(24)); scene.resetSeed(); // There are 12 wild boss floors @@ -1069,19 +1069,19 @@ export function calculateRareSpawnAggregateStats(scene: BattleScene, luckValue: const tier = tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE; switch (tier) { - default: - case BiomePoolTier.BOSS: - ++bossEncountersByRarity[0]; - break; - case BiomePoolTier.BOSS_RARE: - ++bossEncountersByRarity[1]; - break; - case BiomePoolTier.BOSS_SUPER_RARE: - ++bossEncountersByRarity[2]; - break; - case BiomePoolTier.BOSS_ULTRA_RARE: - ++bossEncountersByRarity[3]; - break; + default: + case BiomePoolTier.BOSS: + ++bossEncountersByRarity[0]; + break; + case BiomePoolTier.BOSS_RARE: + ++bossEncountersByRarity[1]; + break; + case BiomePoolTier.BOSS_SUPER_RARE: + ++bossEncountersByRarity[2]; + break; + case BiomePoolTier.BOSS_ULTRA_RARE: + ++bossEncountersByRarity[3]; + break; } } diff --git a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts index 81312f5cb50..564519c0ed7 100644 --- a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts @@ -210,7 +210,7 @@ export function getRandomSpeciesByStarterTier(starterTiers: number | [number, nu let max = Array.isArray(starterTiers) ? starterTiers[1] : starterTiers; let filteredSpecies: [PokemonSpecies, number][] = Object.keys(speciesStarterCosts) - .map(s => [parseInt(s) as Species, speciesStarterCosts[s] as number]) + .map(s => [ parseInt(s) as Species, speciesStarterCosts[s] as number ]) .filter(s => { const pokemonSpecies = getPokemonSpecies(s[0]); return pokemonSpecies && (!excludedSpecies || !excludedSpecies.includes(s[0])) @@ -218,7 +218,7 @@ export function getRandomSpeciesByStarterTier(starterTiers: number | [number, nu && (allowLegendary || !pokemonSpecies.legendary) && (allowMythical || !pokemonSpecies.mythical); }) - .map(s => [getPokemonSpecies(s[0]), s[1]]); + .map(s => [ getPokemonSpecies(s[0]), s[1] ]); if (types && types.length > 0) { filteredSpecies = filteredSpecies.filter(s => types.includes(s[0].type1) || (!isNullOrUndefined(s[0].type2) && types.includes(s[0].type2))); @@ -315,7 +315,7 @@ export function applyHealToPokemon(scene: BattleScene, pokemon: PlayerPokemon, h */ export async function modifyPlayerPokemonBST(pokemon: PlayerPokemon, value: number) { const modType = modifierTypes.MYSTERY_ENCOUNTER_SHUCKLE_JUICE() - .generateType(pokemon.scene.getParty(), [value]) + .generateType(pokemon.scene.getParty(), [ value ]) ?.withIdFromFunc(modifierTypes.MYSTERY_ENCOUNTER_SHUCKLE_JUICE); const modifier = modType?.newModifier(pokemon); if (modifier) { @@ -604,7 +604,7 @@ export async function catchPokemon(scene: BattleScene, pokemon: EnemyPokemon, po } }); }; - Promise.all([pokemon.hideInfo(), scene.gameData.setPokemonCaught(pokemon)]).then(() => { + Promise.all([ pokemon.hideInfo(), scene.gameData.setPokemonCaught(pokemon) ]).then(() => { if (scene.getParty().length === 6) { const promptRelease = () => { scene.ui.showText(i18next.t("battle:partyFull", { pokemonName: pokemon.getNameToRender() }), null, () => { @@ -730,33 +730,33 @@ export function doPlayerFlee(scene: BattleScene, pokemon: EnemyPokemon): Promise * Bug Species and their corresponding weights */ const GOLDEN_BUG_NET_SPECIES_POOL: [Species, number][] = [ - [Species.SCYTHER, 40], - [Species.SCIZOR, 40], - [Species.KLEAVOR, 40], - [Species.PINSIR, 40], - [Species.HERACROSS, 40], - [Species.YANMA, 40], - [Species.YANMEGA, 40], - [Species.SHUCKLE, 40], - [Species.ANORITH, 40], - [Species.ARMALDO, 40], - [Species.ESCAVALIER, 40], - [Species.ACCELGOR, 40], - [Species.JOLTIK, 40], - [Species.GALVANTULA, 40], - [Species.DURANT, 40], - [Species.LARVESTA, 40], - [Species.VOLCARONA, 40], - [Species.DEWPIDER, 40], - [Species.ARAQUANID, 40], - [Species.WIMPOD, 40], - [Species.GOLISOPOD, 40], - [Species.SIZZLIPEDE, 40], - [Species.CENTISKORCH, 40], - [Species.NYMBLE, 40], - [Species.LOKIX, 40], - [Species.BUZZWOLE, 1], - [Species.PHEROMOSA, 1], + [ Species.SCYTHER, 40 ], + [ Species.SCIZOR, 40 ], + [ Species.KLEAVOR, 40 ], + [ Species.PINSIR, 40 ], + [ Species.HERACROSS, 40 ], + [ Species.YANMA, 40 ], + [ Species.YANMEGA, 40 ], + [ Species.SHUCKLE, 40 ], + [ Species.ANORITH, 40 ], + [ Species.ARMALDO, 40 ], + [ Species.ESCAVALIER, 40 ], + [ Species.ACCELGOR, 40 ], + [ Species.JOLTIK, 40 ], + [ Species.GALVANTULA, 40 ], + [ Species.DURANT, 40 ], + [ Species.LARVESTA, 40 ], + [ Species.VOLCARONA, 40 ], + [ Species.DEWPIDER, 40 ], + [ Species.ARAQUANID, 40 ], + [ Species.WIMPOD, 40 ], + [ Species.GOLISOPOD, 40 ], + [ Species.SIZZLIPEDE, 40 ], + [ Species.CENTISKORCH, 40 ], + [ Species.NYMBLE, 40 ], + [ Species.LOKIX, 40 ], + [ Species.BUZZWOLE, 1 ], + [ Species.PHEROMOSA, 1 ], ]; /** diff --git a/src/data/nature.ts b/src/data/nature.ts index c614be465c3..edac06f1a4f 100644 --- a/src/data/nature.ts +++ b/src/data/nature.ts @@ -37,76 +37,76 @@ export function getNatureName(nature: Nature, includeStatEffects: boolean = fals export function getNatureStatMultiplier(nature: Nature, stat: Stat): number { switch (stat) { - case Stat.ATK: - switch (nature) { - case Nature.LONELY: - case Nature.BRAVE: - case Nature.ADAMANT: - case Nature.NAUGHTY: - return 1.1; - case Nature.BOLD: - case Nature.TIMID: - case Nature.MODEST: - case Nature.CALM: - return 0.9; - } - break; - case Stat.DEF: - switch (nature) { - case Nature.BOLD: - case Nature.RELAXED: - case Nature.IMPISH: - case Nature.LAX: - return 1.1; - case Nature.LONELY: - case Nature.HASTY: - case Nature.MILD: - case Nature.GENTLE: - return 0.9; - } - break; - case Stat.SPATK: - switch (nature) { - case Nature.MODEST: - case Nature.MILD: - case Nature.QUIET: - case Nature.RASH: - return 1.1; - case Nature.ADAMANT: - case Nature.IMPISH: - case Nature.JOLLY: - case Nature.CAREFUL: - return 0.9; - } - break; - case Stat.SPDEF: - switch (nature) { - case Nature.CALM: - case Nature.GENTLE: - case Nature.SASSY: - case Nature.CAREFUL: - return 1.1; - case Nature.NAUGHTY: - case Nature.LAX: - case Nature.NAIVE: - case Nature.RASH: - return 0.9; - } - break; - case Stat.SPD: - switch (nature) { - case Nature.TIMID: - case Nature.HASTY: - case Nature.JOLLY: - case Nature.NAIVE: - return 1.1; - case Nature.BRAVE: - case Nature.RELAXED: - case Nature.QUIET: - case Nature.SASSY: - return 0.9; - } - break; + case Stat.ATK: + switch (nature) { + case Nature.LONELY: + case Nature.BRAVE: + case Nature.ADAMANT: + case Nature.NAUGHTY: + return 1.1; + case Nature.BOLD: + case Nature.TIMID: + case Nature.MODEST: + case Nature.CALM: + return 0.9; + } + break; + case Stat.DEF: + switch (nature) { + case Nature.BOLD: + case Nature.RELAXED: + case Nature.IMPISH: + case Nature.LAX: + return 1.1; + case Nature.LONELY: + case Nature.HASTY: + case Nature.MILD: + case Nature.GENTLE: + return 0.9; + } + break; + case Stat.SPATK: + switch (nature) { + case Nature.MODEST: + case Nature.MILD: + case Nature.QUIET: + case Nature.RASH: + return 1.1; + case Nature.ADAMANT: + case Nature.IMPISH: + case Nature.JOLLY: + case Nature.CAREFUL: + return 0.9; + } + break; + case Stat.SPDEF: + switch (nature) { + case Nature.CALM: + case Nature.GENTLE: + case Nature.SASSY: + case Nature.CAREFUL: + return 1.1; + case Nature.NAUGHTY: + case Nature.LAX: + case Nature.NAIVE: + case Nature.RASH: + return 0.9; + } + break; + case Stat.SPD: + switch (nature) { + case Nature.TIMID: + case Nature.HASTY: + case Nature.JOLLY: + case Nature.NAIVE: + return 1.1; + case Nature.BRAVE: + case Nature.RELAXED: + case Nature.QUIET: + case Nature.SASSY: + return 0.9; + } + break; } return 1; diff --git a/src/data/pokeball.ts b/src/data/pokeball.ts index 59ff4ed86ce..57a78e2cd61 100644 --- a/src/data/pokeball.ts +++ b/src/data/pokeball.ts @@ -8,77 +8,77 @@ export const MAX_PER_TYPE_POKEBALLS: integer = 99; export function getPokeballAtlasKey(type: PokeballType): string { switch (type) { - case PokeballType.POKEBALL: - return "pb"; - case PokeballType.GREAT_BALL: - return "gb"; - case PokeballType.ULTRA_BALL: - return "ub"; - case PokeballType.ROGUE_BALL: - return "rb"; - case PokeballType.MASTER_BALL: - return "mb"; - case PokeballType.LUXURY_BALL: - return "lb"; + case PokeballType.POKEBALL: + return "pb"; + case PokeballType.GREAT_BALL: + return "gb"; + case PokeballType.ULTRA_BALL: + return "ub"; + case PokeballType.ROGUE_BALL: + return "rb"; + case PokeballType.MASTER_BALL: + return "mb"; + case PokeballType.LUXURY_BALL: + return "lb"; } } export function getPokeballName(type: PokeballType): string { let ret: string; switch (type) { - case PokeballType.POKEBALL: - ret = i18next.t("pokeball:pokeBall"); - break; - case PokeballType.GREAT_BALL: - ret = i18next.t("pokeball:greatBall"); - break; - case PokeballType.ULTRA_BALL: - ret = i18next.t("pokeball:ultraBall"); - break; - case PokeballType.ROGUE_BALL: - ret = i18next.t("pokeball:rogueBall"); - break; - case PokeballType.MASTER_BALL: - ret = i18next.t("pokeball:masterBall"); - break; - case PokeballType.LUXURY_BALL: - ret = i18next.t("pokeball:luxuryBall"); - break; + case PokeballType.POKEBALL: + ret = i18next.t("pokeball:pokeBall"); + break; + case PokeballType.GREAT_BALL: + ret = i18next.t("pokeball:greatBall"); + break; + case PokeballType.ULTRA_BALL: + ret = i18next.t("pokeball:ultraBall"); + break; + case PokeballType.ROGUE_BALL: + ret = i18next.t("pokeball:rogueBall"); + break; + case PokeballType.MASTER_BALL: + ret = i18next.t("pokeball:masterBall"); + break; + case PokeballType.LUXURY_BALL: + ret = i18next.t("pokeball:luxuryBall"); + break; } return ret; } export function getPokeballCatchMultiplier(type: PokeballType): number { switch (type) { - case PokeballType.POKEBALL: - return 1; - case PokeballType.GREAT_BALL: - return 1.5; - case PokeballType.ULTRA_BALL: - return 2; - case PokeballType.ROGUE_BALL: - return 3; - case PokeballType.MASTER_BALL: - return -1; - case PokeballType.LUXURY_BALL: - return 1; + case PokeballType.POKEBALL: + return 1; + case PokeballType.GREAT_BALL: + return 1.5; + case PokeballType.ULTRA_BALL: + return 2; + case PokeballType.ROGUE_BALL: + return 3; + case PokeballType.MASTER_BALL: + return -1; + case PokeballType.LUXURY_BALL: + return 1; } } export function getPokeballTintColor(type: PokeballType): number { switch (type) { - case PokeballType.POKEBALL: - return 0xd52929; - case PokeballType.GREAT_BALL: - return 0x94b4de; - case PokeballType.ULTRA_BALL: - return 0xe6cd31; - case PokeballType.ROGUE_BALL: - return 0xd52929; - case PokeballType.MASTER_BALL: - return 0xa441bd; - case PokeballType.LUXURY_BALL: - return 0xffde6a; + case PokeballType.POKEBALL: + return 0xd52929; + case PokeballType.GREAT_BALL: + return 0x94b4de; + case PokeballType.ULTRA_BALL: + return 0xe6cd31; + case PokeballType.ROGUE_BALL: + return 0xd52929; + case PokeballType.MASTER_BALL: + return 0xa441bd; + case PokeballType.LUXURY_BALL: + return 0xffde6a; } } diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index 37d8e5d2ffb..7cc20d50fb9 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -640,18 +640,18 @@ export const pokemonFormChanges: PokemonFormChanges = { new SpeciesFormChange(Species.ALTARIA, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.ALTARIANITE)) ], [Species.CASTFORM]: [ - new SpeciesFormChange(Species.CASTFORM, "", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true), - new SpeciesFormChange(Species.CASTFORM, "rainy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true), - new SpeciesFormChange(Species.CASTFORM, "snowy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.SUNNY, WeatherType.HARSH_SUN]), true), - new SpeciesFormChange(Species.CASTFORM, "", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true), - new SpeciesFormChange(Species.CASTFORM, "sunny", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true), - new SpeciesFormChange(Species.CASTFORM, "snowy", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.RAIN, WeatherType.HEAVY_RAIN]), true), - new SpeciesFormChange(Species.CASTFORM, "", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true), - new SpeciesFormChange(Species.CASTFORM, "sunny", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true), - new SpeciesFormChange(Species.CASTFORM, "rainy", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [WeatherType.HAIL, WeatherType.SNOW]), true), - new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true), - new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true), - new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG]), true), + new SpeciesFormChange(Species.CASTFORM, "", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true), + new SpeciesFormChange(Species.CASTFORM, "rainy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true), + new SpeciesFormChange(Species.CASTFORM, "snowy", "sunny", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.SUNNY, WeatherType.HARSH_SUN ]), true), + new SpeciesFormChange(Species.CASTFORM, "", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.RAIN, WeatherType.HEAVY_RAIN ]), true), + new SpeciesFormChange(Species.CASTFORM, "sunny", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.RAIN, WeatherType.HEAVY_RAIN ]), true), + new SpeciesFormChange(Species.CASTFORM, "snowy", "rainy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.RAIN, WeatherType.HEAVY_RAIN ]), true), + new SpeciesFormChange(Species.CASTFORM, "", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.HAIL, WeatherType.SNOW ]), true), + new SpeciesFormChange(Species.CASTFORM, "sunny", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.HAIL, WeatherType.SNOW ]), true), + new SpeciesFormChange(Species.CASTFORM, "rainy", "snowy", new SpeciesFormChangeWeatherTrigger(Abilities.FORECAST, [ WeatherType.HAIL, WeatherType.SNOW ]), true), + new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG ]), true), + new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG ]), true), + new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeRevertWeatherFormTrigger(Abilities.FORECAST, [ WeatherType.NONE, WeatherType.SANDSTORM, WeatherType.STRONG_WINDS, WeatherType.FOG ]), true), new SpeciesFormChange(Species.CASTFORM, "sunny", "", new SpeciesFormChangeActiveTrigger(), true), new SpeciesFormChange(Species.CASTFORM, "rainy", "", new SpeciesFormChangeActiveTrigger(), true), new SpeciesFormChange(Species.CASTFORM, "snowy", "", new SpeciesFormChangeActiveTrigger(), true) @@ -799,8 +799,8 @@ export const pokemonFormChanges: PokemonFormChanges = { [Species.ZYGARDE]: [ new SpeciesFormChange(Species.ZYGARDE, "50-pc", "complete", new SpeciesFormChangeManualTrigger(), true), new SpeciesFormChange(Species.ZYGARDE, "complete", "50-pc", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.ZYGARDE, "10-pc", "complete", new SpeciesFormChangeManualTrigger(), true), - new SpeciesFormChange(Species.ZYGARDE, "complete", "10-pc", new SpeciesFormChangeManualTrigger(), true) + new SpeciesFormChange(Species.ZYGARDE, "10-pc", "10-complete", new SpeciesFormChangeManualTrigger(), true), + new SpeciesFormChange(Species.ZYGARDE, "10-complete", "10-pc", new SpeciesFormChangeManualTrigger(), true) ], [Species.DIANCIE]: [ new SpeciesFormChange(Species.DIANCIE, "", SpeciesFormKey.MEGA, new SpeciesFormChangeItemTrigger(FormChangeItem.DIANCITE)) diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 469e400a551..947ac939989 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -238,8 +238,8 @@ export abstract class PokemonSpeciesForm { isRareRegional(): boolean { switch (this.getRegion()) { - case Region.HISUI: - return true; + case Region.HISUI: + return true; } return false; @@ -265,14 +265,14 @@ export abstract class PokemonSpeciesForm { getBaseExp(): number { let ret = this.baseExp; switch (this.getFormSpriteKey()) { - case SpeciesFormKey.MEGA: - case SpeciesFormKey.MEGA_X: - case SpeciesFormKey.MEGA_Y: - case SpeciesFormKey.PRIMAL: - case SpeciesFormKey.GIGANTAMAX: - case SpeciesFormKey.ETERNAMAX: - ret *= 1.5; - break; + case SpeciesFormKey.MEGA: + case SpeciesFormKey.MEGA_X: + case SpeciesFormKey.MEGA_Y: + case SpeciesFormKey.PRIMAL: + case SpeciesFormKey.GIGANTAMAX: + case SpeciesFormKey.ETERNAMAX: + ret *= 1.5; + break; } return ret; } @@ -346,29 +346,29 @@ export abstract class PokemonSpeciesForm { } switch (this.speciesId) { - case Species.HIPPOPOTAS: - case Species.HIPPOWDON: - case Species.UNFEZANT: - case Species.FRILLISH: - case Species.JELLICENT: - case Species.PYROAR: - ret += female ? "-f" : ""; - break; + case Species.HIPPOPOTAS: + case Species.HIPPOWDON: + case Species.UNFEZANT: + case Species.FRILLISH: + case Species.JELLICENT: + case Species.PYROAR: + ret += female ? "-f" : ""; + break; } let formSpriteKey = this.getFormSpriteKey(formIndex); if (formSpriteKey) { switch (this.speciesId) { - case Species.DUDUNSPARCE: - break; - case Species.ZACIAN: - case Species.ZAMAZENTA: - if (formSpriteKey.startsWith("behemoth")) { - formSpriteKey = "crowned"; - } - default: - ret += `-${formSpriteKey}`; - break; + case Species.DUDUNSPARCE: + break; + case Species.ZACIAN: + case Species.ZAMAZENTA: + if (formSpriteKey.startsWith("behemoth")) { + formSpriteKey = "crowned"; + } + default: + ret += `-${formSpriteKey}`; + break; } } @@ -383,15 +383,15 @@ export abstract class PokemonSpeciesForm { let speciesId = this.speciesId; if (this.speciesId > 2000) { switch (this.speciesId) { - case Species.GALAR_SLOWPOKE: - break; - case Species.ETERNAL_FLOETTE: - break; - case Species.BLOODMOON_URSALUNA: - break; - default: - speciesId = speciesId % 2000; - break; + case Species.GALAR_SLOWPOKE: + break; + case Species.ETERNAL_FLOETTE: + break; + case Species.BLOODMOON_URSALUNA: + break; + default: + speciesId = speciesId % 2000; + break; } } let ret = speciesId.toString(); @@ -403,43 +403,44 @@ export abstract class PokemonSpeciesForm { } const formKey = forms[formIndex || 0].formKey; switch (formKey) { - case SpeciesFormKey.MEGA: - case SpeciesFormKey.MEGA_X: - case SpeciesFormKey.MEGA_Y: - case SpeciesFormKey.GIGANTAMAX: - case SpeciesFormKey.GIGANTAMAX_SINGLE: - case SpeciesFormKey.GIGANTAMAX_RAPID: - case "white": - case "black": - case "therian": - case "sky": - case "gorging": - case "gulping": - case "no-ice": - case "hangry": - case "crowned": - case "eternamax": - case "four": - case "droopy": - case "stretchy": - case "hero": - case "roaming": - case "complete": - case "10": - case "10-pc": - case "super": - case "unbound": - case "pau": - case "pompom": - case "sensu": - case "dusk": - case "midnight": - case "school": - case "dawn-wings": - case "dusk-mane": - case "ultra": - ret += `-${formKey}`; - break; + case SpeciesFormKey.MEGA: + case SpeciesFormKey.MEGA_X: + case SpeciesFormKey.MEGA_Y: + case SpeciesFormKey.GIGANTAMAX: + case SpeciesFormKey.GIGANTAMAX_SINGLE: + case SpeciesFormKey.GIGANTAMAX_RAPID: + case "white": + case "black": + case "therian": + case "sky": + case "gorging": + case "gulping": + case "no-ice": + case "hangry": + case "crowned": + case "eternamax": + case "four": + case "droopy": + case "stretchy": + case "hero": + case "roaming": + case "complete": + case "10-complete": + case "10": + case "10-pc": + case "super": + case "unbound": + case "pau": + case "pompom": + case "sensu": + case "dusk": + case "midnight": + case "school": + case "dawn-wings": + case "dusk-mane": + case "ultra": + ret += `-${formKey}`; + break; } } return ret; @@ -635,23 +636,23 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali const form = this.forms[formIndex]; let key: string | null; switch (form.formKey) { - case SpeciesFormKey.MEGA: - case SpeciesFormKey.PRIMAL: - case SpeciesFormKey.ETERNAMAX: - case SpeciesFormKey.MEGA_X: - case SpeciesFormKey.MEGA_Y: - key = form.formKey; - break; - default: - if (form.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1) { - key = "gigantamax"; - } else { - key = null; - } + case SpeciesFormKey.MEGA: + case SpeciesFormKey.PRIMAL: + case SpeciesFormKey.ETERNAMAX: + case SpeciesFormKey.MEGA_X: + case SpeciesFormKey.MEGA_Y: + key = form.formKey; + break; + default: + if (form.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) > -1) { + key = "gigantamax"; + } else { + key = null; + } } if (key) { - return i18next.t(`battlePokemonForm:${key}`, {pokemonName: this.name}); + return i18next.t(`battlePokemonForm:${key}`, { pokemonName: this.name }); } } return this.name; @@ -689,18 +690,18 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali */ private getStrengthLevelDiff(strength: PartyMemberStrength): integer { switch (Math.min(strength, PartyMemberStrength.STRONGER)) { - case PartyMemberStrength.WEAKEST: - return 60; - case PartyMemberStrength.WEAKER: - return 40; - case PartyMemberStrength.WEAK: - return 20; - case PartyMemberStrength.AVERAGE: - return 8; - case PartyMemberStrength.STRONG: - return 4; - default: - return 0; + case PartyMemberStrength.WEAKEST: + return 60; + case PartyMemberStrength.WEAKER: + return 40; + case PartyMemberStrength.WEAK: + return 20; + case PartyMemberStrength.AVERAGE: + return 8; + case PartyMemberStrength.STRONG: + return 4; + default: + return 0; } } @@ -915,7 +916,7 @@ export class PokemonForm extends PokemonSpeciesForm { public formSpriteKey: string | null; // This is a collection of form keys that have in-run form changes, but should still be separately selectable from the start screen - private starterSelectableKeys: string[] = ["10", "50", "10-pc", "50-pc", "red", "orange", "yellow", "green", "blue", "indigo", "violet"]; + private starterSelectableKeys: string[] = [ "10", "50", "10-pc", "50-pc", "red", "orange", "yellow", "green", "blue", "indigo", "violet" ]; constructor(formName: string, formKey: string, type1: Type, type2: Type | null, height: number, weight: number, ability1: Abilities, ability2: Abilities, abilityHidden: Abilities, baseTotal: integer, baseHp: integer, baseAtk: integer, baseDef: integer, baseSpatk: integer, baseSpdef: integer, baseSpd: integer, @@ -975,7 +976,7 @@ export function initSpecies() { new PokemonSpecies(Species.VENUSAUR, 1, false, false, false, "Seed Pokémon", Type.GRASS, Type.POISON, 2, 100, Abilities.OVERGROW, Abilities.NONE, Abilities.CHLOROPHYLL, 525, 80, 82, 83, 100, 100, 80, 45, 50, 263, GrowthRate.MEDIUM_SLOW, 87.5, true, true, new PokemonForm("Normal", "", Type.GRASS, Type.POISON, 2, 100, Abilities.OVERGROW, Abilities.NONE, Abilities.CHLOROPHYLL, 525, 80, 82, 83, 100, 100, 80, 45, 50, 263, true, null, true), new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.GRASS, Type.POISON, 2.4, 155.5, Abilities.THICK_FAT, Abilities.THICK_FAT, Abilities.THICK_FAT, 625, 80, 100, 123, 122, 120, 80, 45, 50, 263, true), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, Type.POISON, 24, 999.9, Abilities.EFFECT_SPORE, Abilities.EFFECT_SPORE, Abilities.EFFECT_SPORE, 625, 120, 82, 98, 130, 115, 80, 45, 50, 263, true), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, Type.POISON, 24, 999.9, Abilities.EFFECT_SPORE, Abilities.NONE, Abilities.EFFECT_SPORE, 625, 120, 82, 98, 130, 115, 80, 45, 50, 263, true), ), new PokemonSpecies(Species.CHARMANDER, 1, false, false, false, "Lizard Pokémon", Type.FIRE, null, 0.6, 8.5, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 309, 39, 52, 43, 60, 50, 65, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false), new PokemonSpecies(Species.CHARMELEON, 1, false, false, false, "Flame Pokémon", Type.FIRE, null, 1.1, 19, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 405, 58, 64, 58, 80, 65, 80, 45, 50, 142, GrowthRate.MEDIUM_SLOW, 87.5, false), @@ -983,20 +984,20 @@ export function initSpecies() { new PokemonForm("Normal", "", Type.FIRE, Type.FLYING, 1.7, 90.5, Abilities.BLAZE, Abilities.NONE, Abilities.SOLAR_POWER, 534, 78, 84, 78, 109, 85, 100, 45, 50, 267, false, null, true), new PokemonForm("Mega X", SpeciesFormKey.MEGA_X, Type.FIRE, Type.DRAGON, 1.7, 110.5, Abilities.TOUGH_CLAWS, Abilities.NONE, Abilities.TOUGH_CLAWS, 634, 78, 130, 111, 130, 85, 100, 45, 50, 267), new PokemonForm("Mega Y", SpeciesFormKey.MEGA_Y, Type.FIRE, Type.FLYING, 1.7, 100.5, Abilities.DROUGHT, Abilities.NONE, Abilities.DROUGHT, 634, 78, 104, 78, 159, 115, 100, 45, 50, 267), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, Type.FLYING, 28, 999.9, Abilities.BERSERK, Abilities.BERSERK, Abilities.BERSERK, 634, 118, 84, 93, 139, 110, 100, 45, 50, 267), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, Type.FLYING, 28, 999.9, Abilities.BERSERK, Abilities.NONE, Abilities.BERSERK, 634, 118, 84, 93, 139, 100, 100, 45, 50, 267), ), new PokemonSpecies(Species.SQUIRTLE, 1, false, false, false, "Tiny Turtle Pokémon", Type.WATER, null, 0.5, 9, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 314, 44, 48, 65, 50, 64, 43, 45, 50, 63, GrowthRate.MEDIUM_SLOW, 87.5, false), new PokemonSpecies(Species.WARTORTLE, 1, false, false, false, "Turtle Pokémon", Type.WATER, null, 1, 22.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 405, 59, 63, 80, 65, 80, 58, 45, 50, 142, GrowthRate.MEDIUM_SLOW, 87.5, false), new PokemonSpecies(Species.BLASTOISE, 1, false, false, false, "Shellfish Pokémon", Type.WATER, null, 1.6, 85.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 530, 79, 83, 100, 85, 105, 78, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true, new PokemonForm("Normal", "", Type.WATER, null, 1.6, 85.5, Abilities.TORRENT, Abilities.NONE, Abilities.RAIN_DISH, 530, 79, 83, 100, 85, 105, 78, 45, 50, 265, false, null, true), new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.WATER, null, 1.6, 101.1, Abilities.MEGA_LAUNCHER, Abilities.NONE, Abilities.MEGA_LAUNCHER, 630, 79, 103, 120, 135, 115, 78, 45, 50, 265), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, Type.STEEL, 25, 999.9, Abilities.SHELL_ARMOR, Abilities.SHELL_ARMOR, Abilities.SHELL_ARMOR, 630, 119, 83, 135, 115, 110, 68, 45, 50, 265), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, Type.STEEL, 25, 999.9, Abilities.SHELL_ARMOR, Abilities.NONE, Abilities.SHELL_ARMOR, 630, 119, 83, 135, 115, 110, 68, 45, 50, 265), ), new PokemonSpecies(Species.CATERPIE, 1, false, false, false, "Worm Pokémon", Type.BUG, null, 0.3, 2.9, Abilities.SHIELD_DUST, Abilities.NONE, Abilities.RUN_AWAY, 195, 45, 30, 35, 20, 20, 45, 255, 50, 39, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.METAPOD, 1, false, false, false, "Cocoon Pokémon", Type.BUG, null, 0.7, 9.9, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 50, 20, 55, 25, 25, 30, 120, 50, 72, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.BUTTERFREE, 1, false, false, false, "Butterfly Pokémon", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, GrowthRate.MEDIUM_FAST, 50, true, true, new PokemonForm("Normal", "", Type.BUG, Type.FLYING, 1.1, 32, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.TINTED_LENS, 395, 60, 45, 50, 90, 80, 70, 45, 50, 198, true, null, true), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.BUG, Type.FLYING, 17, 999.9, Abilities.COMPOUND_EYES, Abilities.COMPOUND_EYES, Abilities.COMPOUND_EYES, 495, 85, 35, 80, 120, 90, 85, 45, 50, 198, true), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.BUG, Type.FLYING, 17, 999.9, Abilities.COMPOUND_EYES, Abilities.NONE, Abilities.COMPOUND_EYES, 495, 85, 35, 80, 120, 90, 85, 45, 50, 198, true), ), new PokemonSpecies(Species.WEEDLE, 1, false, false, false, "Hairy Bug Pokémon", Type.BUG, Type.POISON, 0.3, 3.2, Abilities.SHIELD_DUST, Abilities.NONE, Abilities.RUN_AWAY, 195, 40, 35, 30, 20, 20, 50, 255, 70, 39, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.KAKUNA, 1, false, false, false, "Cocoon Pokémon", Type.BUG, Type.POISON, 0.6, 10, Abilities.SHED_SKIN, Abilities.NONE, Abilities.SHED_SKIN, 205, 45, 25, 50, 25, 25, 35, 120, 70, 72, GrowthRate.MEDIUM_FAST, 50, false), @@ -1025,7 +1026,7 @@ export function initSpecies() { new PokemonForm("Cute Cosplay", "cute-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom new PokemonForm("Smart Cosplay", "smart-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom new PokemonForm("Tough Cosplay", "tough-cosplay", Type.ELECTRIC, null, 0.4, 6, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 430, 45, 80, 50, 75, 60, 120, 190, 50, 112, true, null, true), //Custom - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ELECTRIC, null, 21, 999.9, Abilities.LIGHTNING_ROD, Abilities.LIGHTNING_ROD, Abilities.LIGHTNING_ROD, 530, 125, 95, 60, 90, 70, 90, 190, 50, 112), //+100 BST from Partner Form + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.ELECTRIC, null, 21, 999.9, Abilities.LIGHTNING_ROD, Abilities.NONE, Abilities.LIGHTNING_ROD, 530, 125, 95, 60, 90, 70, 90, 190, 50, 112), //+100 BST from Partner Form ), new PokemonSpecies(Species.RAICHU, 1, false, false, false, "Mouse Pokémon", Type.ELECTRIC, null, 0.8, 30, Abilities.STATIC, Abilities.NONE, Abilities.LIGHTNING_ROD, 485, 60, 90, 55, 90, 80, 110, 75, 50, 243, GrowthRate.MEDIUM_FAST, 50, true), new PokemonSpecies(Species.SANDSHREW, 1, false, false, false, "Mouse Pokémon", Type.GROUND, null, 0.6, 12, Abilities.SAND_VEIL, Abilities.NONE, Abilities.SAND_RUSH, 300, 50, 75, 85, 20, 30, 40, 255, 50, 60, GrowthRate.MEDIUM_FAST, 50, false), @@ -1110,7 +1111,7 @@ export function initSpecies() { new PokemonSpecies(Species.GENGAR, 1, false, false, false, "Shadow Pokémon", Type.GHOST, Type.POISON, 1.5, 40.5, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 500, 60, 65, 60, 130, 75, 110, 45, 50, 250, GrowthRate.MEDIUM_SLOW, 50, false, true, new PokemonForm("Normal", "", Type.GHOST, Type.POISON, 1.5, 40.5, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 500, 60, 65, 60, 130, 75, 110, 45, 50, 250, false, null, true), new PokemonForm("Mega", SpeciesFormKey.MEGA, Type.GHOST, Type.POISON, 1.4, 40.5, Abilities.SHADOW_TAG, Abilities.NONE, Abilities.NONE, 600, 60, 65, 80, 170, 95, 130, 45, 50, 250), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GHOST, Type.POISON, 20, 999.9, Abilities.CURSED_BODY, Abilities.CURSED_BODY, Abilities.CURSED_BODY, 600, 140, 65, 70, 140, 85, 100, 45, 50, 250), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GHOST, Type.POISON, 20, 999.9, Abilities.CURSED_BODY, Abilities.NONE, Abilities.NONE, 600, 140, 65, 70, 140, 85, 100, 45, 50, 250), ), new PokemonSpecies(Species.ONIX, 1, false, false, false, "Rock Snake Pokémon", Type.ROCK, Type.GROUND, 8.8, 210, Abilities.ROCK_HEAD, Abilities.STURDY, Abilities.WEAK_ARMOR, 385, 35, 45, 160, 30, 45, 70, 45, 50, 77, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.DROWZEE, 1, false, false, false, "Hypnosis Pokémon", Type.PSYCHIC, null, 1, 32.4, Abilities.INSOMNIA, Abilities.FOREWARN, Abilities.INNER_FOCUS, 328, 60, 48, 45, 43, 90, 42, 190, 70, 66, GrowthRate.MEDIUM_FAST, 50, false), @@ -1118,7 +1119,7 @@ export function initSpecies() { new PokemonSpecies(Species.KRABBY, 1, false, false, false, "River Crab Pokémon", Type.WATER, null, 0.4, 6.5, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 325, 30, 105, 90, 25, 25, 50, 225, 50, 65, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.KINGLER, 1, false, false, false, "Pincer Pokémon", Type.WATER, null, 1.3, 60, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 475, 55, 130, 115, 50, 50, 75, 60, 50, 166, GrowthRate.MEDIUM_FAST, 50, false, true, new PokemonForm("Normal", "", Type.WATER, null, 1.3, 60, Abilities.HYPER_CUTTER, Abilities.SHELL_ARMOR, Abilities.SHEER_FORCE, 475, 55, 130, 115, 50, 50, 75, 60, 50, 166, false, null, true), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 19, 999.9, Abilities.TOUGH_CLAWS, Abilities.TOUGH_CLAWS, Abilities.TOUGH_CLAWS, 575, 90, 155, 140, 50, 80, 70, 60, 50, 166), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 19, 999.9, Abilities.TOUGH_CLAWS, Abilities.TOUGH_CLAWS, Abilities.TOUGH_CLAWS, 575, 90, 155, 140, 50, 70, 70, 60, 50, 166), ), new PokemonSpecies(Species.VOLTORB, 1, false, false, false, "Ball Pokémon", Type.ELECTRIC, null, 0.5, 10.4, Abilities.SOUNDPROOF, Abilities.STATIC, Abilities.AFTERMATH, 330, 40, 30, 50, 55, 55, 100, 190, 70, 66, GrowthRate.MEDIUM_FAST, null, false), new PokemonSpecies(Species.ELECTRODE, 1, false, false, false, "Ball Pokémon", Type.ELECTRIC, null, 1.2, 66.6, Abilities.SOUNDPROOF, Abilities.STATIC, Abilities.AFTERMATH, 490, 60, 50, 70, 80, 80, 150, 60, 70, 172, GrowthRate.MEDIUM_FAST, null, false), @@ -2135,7 +2136,8 @@ export function initSpecies() { new PokemonForm("10% Forme", "10", Type.DRAGON, Type.GROUND, 1.2, 33.5, Abilities.AURA_BREAK, Abilities.NONE, Abilities.NONE, 486, 54, 100, 71, 61, 85, 115, 3, 0, 300, false, null, true), new PokemonForm("50% Forme Power Construct", "50-pc", Type.DRAGON, Type.GROUND, 5, 305, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 600, 108, 100, 121, 81, 95, 95, 3, 0, 300, false, "", true), new PokemonForm("10% Forme Power Construct", "10-pc", Type.DRAGON, Type.GROUND, 1.2, 33.5, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 486, 54, 100, 71, 61, 85, 115, 3, 0, 300, false, "10", true), - new PokemonForm("Complete Forme", "complete", Type.DRAGON, Type.GROUND, 4.5, 610, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 708, 216, 100, 121, 91, 95, 85, 3, 0, 300), + new PokemonForm("Complete Forme (50% PC)", "complete", Type.DRAGON, Type.GROUND, 4.5, 610, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 708, 216, 100, 121, 91, 95, 85, 3, 0, 300), + new PokemonForm("Complete Forme (10% PC)", "10-complete", Type.DRAGON, Type.GROUND, 4.5, 610, Abilities.POWER_CONSTRUCT, Abilities.NONE, Abilities.NONE, 708, 216, 100, 121, 91, 95, 85, 3, 0, 300, false, "complete"), ), new PokemonSpecies(Species.DIANCIE, 6, false, false, true, "Jewel Pokémon", Type.ROCK, Type.FAIRY, 0.7, 8.8, Abilities.CLEAR_BODY, Abilities.NONE, Abilities.NONE, 600, 50, 100, 150, 100, 150, 50, 3, 50, 300, GrowthRate.SLOW, null, false, true, new PokemonForm("Normal", "", Type.ROCK, Type.FAIRY, 0.7, 8.8, Abilities.CLEAR_BODY, Abilities.NONE, Abilities.NONE, 600, 50, 100, 150, 100, 150, 50, 3, 50, 300, false, null, true), @@ -2298,25 +2300,25 @@ export function initSpecies() { new PokemonSpecies(Species.MELTAN, 7, false, false, true, "Hex Nut Pokémon", Type.STEEL, null, 0.2, 8, Abilities.MAGNET_PULL, Abilities.NONE, Abilities.NONE, 300, 46, 65, 65, 55, 35, 34, 3, 0, 150, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.MELMETAL, 7, false, false, true, "Hex Nut Pokémon", Type.STEEL, null, 2.5, 800, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 600, 135, 143, 143, 80, 65, 34, 3, 0, 300, GrowthRate.SLOW, null, false, true, new PokemonForm("Normal", "", Type.STEEL, null, 2.5, 800, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 600, 135, 143, 143, 80, 65, 34, 3, 0, 300, false, null, true), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, null, 25, 999.9, Abilities.IRON_FIST, Abilities.IRON_FIST, Abilities.IRON_FIST, 700, 175, 165, 155, 85, 75, 45, 3, 0, 300), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, null, 25, 999.9, Abilities.IRON_FIST, Abilities.NONE, Abilities.NONE, 700, 175, 165, 155, 85, 75, 45, 3, 0, 300), ), new PokemonSpecies(Species.GROOKEY, 8, false, false, false, "Chimp Pokémon", Type.GRASS, null, 0.3, 5, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 310, 50, 65, 50, 40, 40, 65, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false), new PokemonSpecies(Species.THWACKEY, 8, false, false, false, "Beat Pokémon", Type.GRASS, null, 0.7, 14, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 420, 70, 85, 70, 55, 60, 80, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false), new PokemonSpecies(Species.RILLABOOM, 8, false, false, false, "Drummer Pokémon", Type.GRASS, null, 2.1, 90, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 530, 100, 125, 90, 60, 70, 85, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true, new PokemonForm("Normal", "", Type.GRASS, null, 2.1, 90, Abilities.OVERGROW, Abilities.NONE, Abilities.GRASSY_SURGE, 530, 100, 125, 90, 60, 70, 85, 45, 50, 265, false, null, true), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, null, 28, 999.9, Abilities.GRASSY_SURGE, Abilities.GRASSY_SURGE, Abilities.GRASSY_SURGE, 630, 125, 150, 105, 85, 85, 80, 45, 50, 265), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.GRASS, null, 28, 999.9, Abilities.GRASSY_SURGE, Abilities.NONE, Abilities.GRASSY_SURGE, 630, 125, 150, 105, 85, 85, 80, 45, 50, 265), ), new PokemonSpecies(Species.SCORBUNNY, 8, false, false, false, "Rabbit Pokémon", Type.FIRE, null, 0.3, 4.5, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 310, 50, 71, 40, 40, 40, 69, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false), new PokemonSpecies(Species.RABOOT, 8, false, false, false, "Rabbit Pokémon", Type.FIRE, null, 0.6, 9, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 420, 65, 86, 60, 55, 60, 94, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false), new PokemonSpecies(Species.CINDERACE, 8, false, false, false, "Striker Pokémon", Type.FIRE, null, 1.4, 33, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 530, 80, 116, 75, 65, 75, 119, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true, new PokemonForm("Normal", "", Type.FIRE, null, 1.4, 33, Abilities.BLAZE, Abilities.NONE, Abilities.LIBERO, 530, 80, 116, 75, 65, 75, 119, 45, 50, 265, false, null, true), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, null, 27, 999.9, Abilities.LIBERO, Abilities.LIBERO, Abilities.LIBERO, 630, 100, 146, 80, 90, 80, 134, 45, 50, 265), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FIRE, null, 27, 999.9, Abilities.LIBERO, Abilities.NONE, Abilities.LIBERO, 630, 100, 146, 80, 90, 80, 134, 45, 50, 265), ), new PokemonSpecies(Species.SOBBLE, 8, false, false, false, "Water Lizard Pokémon", Type.WATER, null, 0.3, 4, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 310, 50, 40, 40, 70, 40, 70, 45, 50, 62, GrowthRate.MEDIUM_SLOW, 87.5, false), new PokemonSpecies(Species.DRIZZILE, 8, false, false, false, "Water Lizard Pokémon", Type.WATER, null, 0.7, 11.5, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 420, 65, 60, 55, 95, 55, 90, 45, 50, 147, GrowthRate.MEDIUM_SLOW, 87.5, false), new PokemonSpecies(Species.INTELEON, 8, false, false, false, "Secret Agent Pokémon", Type.WATER, null, 1.9, 45.2, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 530, 70, 85, 65, 125, 65, 120, 45, 50, 265, GrowthRate.MEDIUM_SLOW, 87.5, false, true, new PokemonForm("Normal", "", Type.WATER, null, 1.9, 45.2, Abilities.TORRENT, Abilities.NONE, Abilities.SNIPER, 530, 70, 85, 65, 125, 65, 120, 45, 50, 265, false, null, true), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 40, 999.9, Abilities.SNIPER, Abilities.SNIPER, Abilities.SNIPER, 630, 95, 97, 77, 147, 77, 137, 45, 50, 265), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.WATER, null, 40, 999.9, Abilities.SNIPER, Abilities.NONE, Abilities.SNIPER, 630, 95, 97, 77, 147, 77, 137, 45, 50, 265), ), new PokemonSpecies(Species.SKWOVET, 8, false, false, false, "Cheeky Pokémon", Type.NORMAL, null, 0.3, 2.5, Abilities.CHEEK_POUCH, Abilities.NONE, Abilities.GLUTTONY, 275, 70, 55, 55, 35, 35, 25, 255, 50, 55, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.GREEDENT, 8, false, false, false, "Greedy Pokémon", Type.NORMAL, null, 0.6, 6, Abilities.CHEEK_POUCH, Abilities.NONE, Abilities.GLUTTONY, 460, 120, 95, 95, 55, 75, 20, 90, 50, 161, GrowthRate.MEDIUM_FAST, 50, false), @@ -2422,7 +2424,7 @@ export function initSpecies() { new PokemonForm("Ruby Swirl", "ruby-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true), new PokemonForm("Caramel Swirl", "caramel-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true), new PokemonForm("Rainbow Swirl", "rainbow-swirl", Type.FAIRY, null, 0.3, 0.5, Abilities.SWEET_VEIL, Abilities.NONE, Abilities.AROMA_VEIL, 495, 65, 60, 75, 110, 121, 64, 100, 50, 173, false, null, true), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FAIRY, null, 30, 999.9, Abilities.MISTY_SURGE, Abilities.MISTY_SURGE, Abilities.MISTY_SURGE, 595, 135, 60, 75, 130, 131, 64, 100, 50, 173), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.FAIRY, null, 30, 999.9, Abilities.MISTY_SURGE, Abilities.NONE, Abilities.MISTY_SURGE, 595, 135, 60, 75, 130, 131, 64, 100, 50, 173), ), new PokemonSpecies(Species.FALINKS, 8, false, false, false, "Formation Pokémon", Type.FIGHTING, null, 3, 62, Abilities.BATTLE_ARMOR, Abilities.NONE, Abilities.DEFIANT, 470, 65, 100, 100, 70, 60, 75, 45, 50, 165, GrowthRate.MEDIUM_FAST, null, false), new PokemonSpecies(Species.PINCURCHIN, 8, false, false, false, "Sea Urchin Pokémon", Type.ELECTRIC, null, 0.3, 1, Abilities.LIGHTNING_ROD, Abilities.NONE, Abilities.ELECTRIC_SURGE, 435, 48, 101, 95, 91, 85, 15, 75, 50, 152, GrowthRate.MEDIUM_FAST, 50, false), @@ -2444,7 +2446,7 @@ export function initSpecies() { new PokemonSpecies(Species.CUFANT, 8, false, false, false, "Copperderm Pokémon", Type.STEEL, null, 1.2, 100, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 330, 72, 80, 49, 40, 49, 40, 190, 50, 66, GrowthRate.MEDIUM_FAST, 50, false), new PokemonSpecies(Species.COPPERAJAH, 8, false, false, false, "Copperderm Pokémon", Type.STEEL, null, 3, 650, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 500, 122, 130, 69, 80, 69, 30, 90, 50, 175, GrowthRate.MEDIUM_FAST, 50, false, true, new PokemonForm("Normal", "", Type.STEEL, null, 3, 650, Abilities.SHEER_FORCE, Abilities.NONE, Abilities.HEAVY_METAL, 500, 122, 130, 69, 80, 69, 30, 90, 50, 175, false, null, true), - new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, Type.GROUND, 23, 999.9, Abilities.MOLD_BREAKER, Abilities.MOLD_BREAKER, Abilities.MOLD_BREAKER, 600, 167, 155, 89, 80, 89, 20, 90, 50, 175), + new PokemonForm("G-Max", SpeciesFormKey.GIGANTAMAX, Type.STEEL, Type.GROUND, 23, 999.9, Abilities.MOLD_BREAKER, Abilities.NONE, Abilities.MOLD_BREAKER, 600, 167, 155, 89, 80, 89, 20, 90, 50, 175), ), new PokemonSpecies(Species.DRACOZOLT, 8, false, false, false, "Fossil Pokémon", Type.ELECTRIC, Type.DRAGON, 1.8, 190, Abilities.VOLT_ABSORB, Abilities.HUSTLE, Abilities.SAND_RUSH, 505, 90, 100, 90, 80, 70, 75, 45, 50, 177, GrowthRate.SLOW, null, false), new PokemonSpecies(Species.ARCTOZOLT, 8, false, false, false, "Fossil Pokémon", Type.ELECTRIC, Type.ICE, 2.3, 150, Abilities.VOLT_ABSORB, Abilities.STATIC, Abilities.SLUSH_RUSH, 505, 90, 100, 90, 90, 80, 55, 45, 50, 177, GrowthRate.SLOW, null, false), diff --git a/src/data/splash-messages.ts b/src/data/splash-messages.ts index a257b748734..1f00ce0d555 100644 --- a/src/data/splash-messages.ts +++ b/src/data/splash-messages.ts @@ -185,26 +185,26 @@ const seasonalSplashMessages: Season[] = [ name: "Halloween", start: "09-15", end: "10-31", - messages: ["halloween.pumpkabooAbout", "halloween.mayContainSpiders", "halloween.spookyScarySkeledirge", "halloween.gourgeistUsedTrickOrTreat", "halloween.letsSnuggleForever"], + messages: [ "halloween.pumpkabooAbout", "halloween.mayContainSpiders", "halloween.spookyScarySkeledirge", "halloween.gourgeistUsedTrickOrTreat", "halloween.letsSnuggleForever" ], }, { name: "XMAS", start: "12-01", end: "12-26", - messages: ["xmas.happyHolidays", "xmas.unaffilicatedWithDelibirdServices", "xmas.delibirdSeason", "xmas.diamondsFromTheSky", "xmas.holidayStylePikachuNotIncluded"], + messages: [ "xmas.happyHolidays", "xmas.unaffilicatedWithDelibirdServices", "xmas.delibirdSeason", "xmas.diamondsFromTheSky", "xmas.holidayStylePikachuNotIncluded" ], }, { name: "New Year's", start: "01-01", end: "01-31", - messages: ["newYears.happyNewYear"], + messages: [ "newYears.happyNewYear" ], }, ]; //#endregion export function getSplashMessages(): string[] { - const splashMessages: string[] = [...commonSplashMessages]; + const splashMessages: string[] = [ ...commonSplashMessages ]; console.log("use seasonal splash messages", USE_SEASONAL_SPLASH_MESSAGES); if (USE_SEASONAL_SPLASH_MESSAGES) { // add seasonal splash messages if the season is active diff --git a/src/data/status-effect.ts b/src/data/status-effect.ts index ffe32a02aeb..4319985f43a 100644 --- a/src/data/status-effect.ts +++ b/src/data/status-effect.ts @@ -26,20 +26,20 @@ export class Status { function getStatusEffectMessageKey(statusEffect: StatusEffect | undefined): string { switch (statusEffect) { - case StatusEffect.POISON: - return "statusEffect:poison"; - case StatusEffect.TOXIC: - return "statusEffect:toxic"; - case StatusEffect.PARALYSIS: - return "statusEffect:paralysis"; - case StatusEffect.SLEEP: - return "statusEffect:sleep"; - case StatusEffect.FREEZE: - return "statusEffect:freeze"; - case StatusEffect.BURN: - return "statusEffect:burn"; - default: - return "statusEffect:none"; + case StatusEffect.POISON: + return "statusEffect:poison"; + case StatusEffect.TOXIC: + return "statusEffect:toxic"; + case StatusEffect.PARALYSIS: + return "statusEffect:paralysis"; + case StatusEffect.SLEEP: + return "statusEffect:sleep"; + case StatusEffect.FREEZE: + return "statusEffect:freeze"; + case StatusEffect.BURN: + return "statusEffect:burn"; + default: + return "statusEffect:none"; } } @@ -90,14 +90,14 @@ export function getStatusEffectDescriptor(statusEffect: StatusEffect): string { export function getStatusEffectCatchRateMultiplier(statusEffect: StatusEffect): number { switch (statusEffect) { - case StatusEffect.POISON: - case StatusEffect.TOXIC: - case StatusEffect.PARALYSIS: - case StatusEffect.BURN: - return 1.5; - case StatusEffect.SLEEP: - case StatusEffect.FREEZE: - return 2.5; + case StatusEffect.POISON: + case StatusEffect.TOXIC: + case StatusEffect.PARALYSIS: + case StatusEffect.BURN: + return 1.5; + case StatusEffect.SLEEP: + case StatusEffect.FREEZE: + return 2.5; } return 1; diff --git a/src/data/terrain.ts b/src/data/terrain.ts index 6db68b92239..d8ee8d67925 100644 --- a/src/data/terrain.ts +++ b/src/data/terrain.ts @@ -34,21 +34,21 @@ export class Terrain { getAttackTypeMultiplier(attackType: Type): number { switch (this.terrainType) { - case TerrainType.ELECTRIC: - if (attackType === Type.ELECTRIC) { - return 1.3; - } - break; - case TerrainType.GRASSY: - if (attackType === Type.GRASS) { - return 1.3; - } - break; - case TerrainType.PSYCHIC: - if (attackType === Type.PSYCHIC) { - return 1.3; - } - break; + case TerrainType.ELECTRIC: + if (attackType === Type.ELECTRIC) { + return 1.3; + } + break; + case TerrainType.GRASSY: + if (attackType === Type.GRASS) { + return 1.3; + } + break; + case TerrainType.PSYCHIC: + if (attackType === Type.PSYCHIC) { + return 1.3; + } + break; } return 1; @@ -56,13 +56,13 @@ export class Terrain { isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move): boolean { switch (this.terrainType) { - case TerrainType.PSYCHIC: - if (!move.hasAttr(ProtectAttr)) { - const priority = new Utils.IntegerHolder(move.priority); - applyAbAttrs(ChangeMovePriorityAbAttr, user, null, false, move, priority); - // Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain - return priority.value > 0 && user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded()); - } + case TerrainType.PSYCHIC: + if (!move.hasAttr(ProtectAttr)) { + const priority = new Utils.IntegerHolder(move.priority); + applyAbAttrs(ChangeMovePriorityAbAttr, user, null, false, move, priority); + // Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain + return priority.value > 0 && user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded()); + } } return false; @@ -71,14 +71,14 @@ export class Terrain { export function getTerrainName(terrainType: TerrainType): string { switch (terrainType) { - case TerrainType.MISTY: - return i18next.t("terrain:misty"); - case TerrainType.ELECTRIC: - return i18next.t("terrain:electric"); - case TerrainType.GRASSY: - return i18next.t("terrain:grassy"); - case TerrainType.PSYCHIC: - return i18next.t("terrain:psychic"); + case TerrainType.MISTY: + return i18next.t("terrain:misty"); + case TerrainType.ELECTRIC: + return i18next.t("terrain:electric"); + case TerrainType.GRASSY: + return i18next.t("terrain:grassy"); + case TerrainType.PSYCHIC: + return i18next.t("terrain:psychic"); } return ""; @@ -87,14 +87,14 @@ export function getTerrainName(terrainType: TerrainType): string { export function getTerrainColor(terrainType: TerrainType): [ integer, integer, integer ] { switch (terrainType) { - case TerrainType.MISTY: - return [ 232, 136, 200 ]; - case TerrainType.ELECTRIC: - return [ 248, 248, 120 ]; - case TerrainType.GRASSY: - return [ 120, 200, 80 ]; - case TerrainType.PSYCHIC: - return [ 160, 64, 160 ]; + case TerrainType.MISTY: + return [ 232, 136, 200 ]; + case TerrainType.ELECTRIC: + return [ 248, 248, 120 ]; + case TerrainType.GRASSY: + return [ 120, 200, 80 ]; + case TerrainType.PSYCHIC: + return [ 160, 64, 160 ]; } return [ 0, 0, 0 ]; diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 462d06b2a28..bc69b611075 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -227,7 +227,7 @@ export class TrainerConfig { this.battleBgm = "battle_trainer"; this.mixedBattleBgm = "battle_trainer"; this.victoryBgm = "victory_trainer"; - this.partyTemplates = [trainerPartyTemplates.TWO_AVG]; + this.partyTemplates = [ trainerPartyTemplates.TWO_AVG ]; this.speciesFilter = species => (allowLegendaries || (!species.legendary && !species.subLegendary && !species.mythical)) && !species.isTrainerForbidden(); } @@ -299,65 +299,65 @@ export class TrainerConfig { getDerivedType(trainerTypeToDeriveFrom: TrainerType | null = null): TrainerType { let trainerType = trainerTypeToDeriveFrom ? trainerTypeToDeriveFrom : this.trainerType; switch (trainerType) { - case TrainerType.RIVAL_2: - case TrainerType.RIVAL_3: - case TrainerType.RIVAL_4: - case TrainerType.RIVAL_5: - case TrainerType.RIVAL_6: - trainerType = TrainerType.RIVAL; - break; - case TrainerType.LANCE_CHAMPION: - trainerType = TrainerType.LANCE; - break; - case TrainerType.LARRY_ELITE: - trainerType = TrainerType.LARRY; - break; - case TrainerType.ROCKET_BOSS_GIOVANNI_1: - case TrainerType.ROCKET_BOSS_GIOVANNI_2: - trainerType = TrainerType.GIOVANNI; - break; - case TrainerType.MAXIE_2: - trainerType = TrainerType.MAXIE; - break; - case TrainerType.ARCHIE_2: - trainerType = TrainerType.ARCHIE; - break; - case TrainerType.CYRUS_2: - trainerType = TrainerType.CYRUS; - break; - case TrainerType.GHETSIS_2: - trainerType = TrainerType.GHETSIS; - break; - case TrainerType.LYSANDRE_2: - trainerType = TrainerType.LYSANDRE; - break; - case TrainerType.LUSAMINE_2: - trainerType = TrainerType.LUSAMINE; - break; - case TrainerType.GUZMA_2: - trainerType = TrainerType.GUZMA; - break; - case TrainerType.ROSE_2: - trainerType = TrainerType.ROSE; - break; - case TrainerType.PENNY_2: - trainerType = TrainerType.PENNY; - break; - case TrainerType.MARNIE_ELITE: - trainerType = TrainerType.MARNIE; - break; - case TrainerType.NESSA_ELITE: - trainerType = TrainerType.NESSA; - break; - case TrainerType.BEA_ELITE: - trainerType = TrainerType.BEA; - break; - case TrainerType.ALLISTER_ELITE: - trainerType = TrainerType.ALLISTER; - break; - case TrainerType.RAIHAN_ELITE: - trainerType = TrainerType.RAIHAN; - break; + case TrainerType.RIVAL_2: + case TrainerType.RIVAL_3: + case TrainerType.RIVAL_4: + case TrainerType.RIVAL_5: + case TrainerType.RIVAL_6: + trainerType = TrainerType.RIVAL; + break; + case TrainerType.LANCE_CHAMPION: + trainerType = TrainerType.LANCE; + break; + case TrainerType.LARRY_ELITE: + trainerType = TrainerType.LARRY; + break; + case TrainerType.ROCKET_BOSS_GIOVANNI_1: + case TrainerType.ROCKET_BOSS_GIOVANNI_2: + trainerType = TrainerType.GIOVANNI; + break; + case TrainerType.MAXIE_2: + trainerType = TrainerType.MAXIE; + break; + case TrainerType.ARCHIE_2: + trainerType = TrainerType.ARCHIE; + break; + case TrainerType.CYRUS_2: + trainerType = TrainerType.CYRUS; + break; + case TrainerType.GHETSIS_2: + trainerType = TrainerType.GHETSIS; + break; + case TrainerType.LYSANDRE_2: + trainerType = TrainerType.LYSANDRE; + break; + case TrainerType.LUSAMINE_2: + trainerType = TrainerType.LUSAMINE; + break; + case TrainerType.GUZMA_2: + trainerType = TrainerType.GUZMA; + break; + case TrainerType.ROSE_2: + trainerType = TrainerType.ROSE; + break; + case TrainerType.PENNY_2: + trainerType = TrainerType.PENNY; + break; + case TrainerType.MARNIE_ELITE: + trainerType = TrainerType.MARNIE; + break; + case TrainerType.NESSA_ELITE: + trainerType = TrainerType.NESSA; + break; + case TrainerType.BEA_ELITE: + trainerType = TrainerType.BEA; + break; + case TrainerType.ALLISTER_ELITE: + trainerType = TrainerType.ALLISTER; + break; + case TrainerType.RAIHAN_ELITE: + trainerType = TrainerType.RAIHAN; + break; } return trainerType; @@ -526,7 +526,7 @@ export class TrainerConfig { } setSpeciesPools(speciesPools: TrainerTierPools | Species[]): TrainerConfig { - this.speciesPools = (Array.isArray(speciesPools) ? {[TrainerPoolTier.COMMON]: speciesPools} : speciesPools) as unknown as TrainerTierPools; + this.speciesPools = (Array.isArray(speciesPools) ? { [TrainerPoolTier.COMMON]: speciesPools } : speciesPools) as unknown as TrainerTierPools; return this; } @@ -564,104 +564,104 @@ export class TrainerConfig { speciesPoolPerEvilTeamAdmin(team): TrainerTierPools { team = team.toLowerCase(); switch (team) { - case "rocket": { - return { - [TrainerPoolTier.COMMON]: [Species.RATTATA, Species.KOFFING, Species.EKANS, Species.ZUBAT, Species.MAGIKARP, Species.HOUNDOUR, Species.ONIX, Species.CUBONE, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB, Species.DROWZEE, Species.VILEPLUME], - [TrainerPoolTier.UNCOMMON]: [Species.PORYGON, Species.MANKEY, Species.MAGNEMITE, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE, Species.PALDEA_TAUROS, Species.OMANYTE, Species.KABUTO, Species.MAGBY, Species.ELEKID], - [TrainerPoolTier.RARE]: [Species.DRATINI, Species.LARVITAR] - }; - } - case "magma": { - return { - [TrainerPoolTier.COMMON]: [Species.GROWLITHE, Species.SLUGMA, Species.SOLROCK, Species.HIPPOPOTAS, Species.BALTOY, Species.ROLYCOLY, Species.GLIGAR, Species.TORKOAL, Species.HOUNDOUR, Species.MAGBY], - [TrainerPoolTier.UNCOMMON]: [Species.TRAPINCH, Species.SILICOBRA, Species.RHYHORN, Species.ANORITH, Species.LILEEP, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON, Species.BARBOACH], - [TrainerPoolTier.RARE]: [Species.CAPSAKID, Species.CHARCADET] - }; - } - case "aqua": { - return { - [TrainerPoolTier.COMMON]: [Species.CORPHISH, Species.SPHEAL, Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.AZURILL, Species.LOTAD, Species.WAILMER, Species.REMORAID], - [TrainerPoolTier.UNCOMMON]: [Species.MANTYKE, Species.HISUI_QWILFISH, Species.ARROKUDA, Species.DHELMISE, Species.CLOBBOPUS, Species.FEEBAS, Species.PALDEA_WOOPER, Species.HORSEA, Species.SKRELP], - [TrainerPoolTier.RARE]: [Species.DONDOZO, Species.BASCULEGION] - }; - } - case "galactic": { - return { - [TrainerPoolTier.COMMON]: [Species.BRONZOR, Species.SWINUB, Species.YANMA, Species.LICKITUNG, Species.TANGELA, Species.MAGBY, Species.ELEKID, Species.SKORUPI, Species.ZUBAT, Species.MURKROW, Species.MAGIKARP, Species.VOLTORB], - [TrainerPoolTier.UNCOMMON]: [Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.SNEASEL, Species.DUSKULL, Species.ROTOM, Species.HISUI_VOLTORB, Species.GLIGAR, Species.ABRA], - [TrainerPoolTier.RARE]: [Species.URSALUNA, Species.HISUI_LILLIGANT, Species.SPIRITOMB, Species.HISUI_SNEASEL] - }; - } - case "plasma": { - return { - [TrainerPoolTier.COMMON]: [Species.YAMASK, Species.ROGGENROLA, Species.JOLTIK, Species.TYMPOLE, Species.FRILLISH, Species.FERROSEED, Species.SANDILE, Species.TIMBURR, Species.DARUMAKA, Species.FOONGUS, Species.CUBCHOO, Species.VANILLITE], - [TrainerPoolTier.UNCOMMON]: [Species.PAWNIARD, Species.VULLABY, Species.ZORUA, Species.DRILBUR, Species.KLINK, Species.TYNAMO, Species.GALAR_DARUMAKA, Species.GOLETT, Species.MIENFOO, Species.DURANT, Species.SIGILYPH], - [TrainerPoolTier.RARE]: [Species.HISUI_ZORUA, Species.AXEW, Species.DEINO, Species.HISUI_BRAVIARY] - }; - } - case "flare": { - return { - [TrainerPoolTier.COMMON]: [Species.FLETCHLING, Species.LITLEO, Species.INKAY, Species.HELIOPTILE, Species.ELECTRIKE, Species.SKORUPI, Species.PURRLOIN, Species.CLAWITZER, Species.PANCHAM, Species.ESPURR, Species.BUNNELBY], - [TrainerPoolTier.UNCOMMON]: [Species.LITWICK, Species.SNEASEL, Species.PUMPKABOO, Species.PHANTUMP, Species.HONEDGE, Species.BINACLE, Species.HOUNDOUR, Species.SKRELP, Species.SLIGGOO], - [TrainerPoolTier.RARE]: [Species.NOIVERN, Species.HISUI_AVALUGG, Species.HISUI_SLIGGOO] - }; - } - case "aether": { - return { - [TrainerPoolTier.COMMON]: [ Species.BRUXISH, Species.SLOWPOKE, Species.BALTOY, Species.EXEGGCUTE, Species.ABRA, Species.ALOLA_RAICHU, Species.ELGYEM, Species.NATU, Species.BLIPBUG, Species.GIRAFARIG, Species.ORANGURU], - [TrainerPoolTier.UNCOMMON]: [Species.GALAR_SLOWPOKE, Species.MEDITITE, Species.BELDUM, Species.HATENNA, Species.INKAY, Species.RALTS, Species.GALAR_MR_MIME], - [TrainerPoolTier.RARE]: [Species.ARMAROUGE, Species.HISUI_BRAVIARY, Species.PORYGON] - }; - } - case "skull": { - return { - [TrainerPoolTier.COMMON]: [ Species.MAREANIE, Species.ALOLA_GRIMER, Species.GASTLY, Species.ZUBAT, Species.FOMANTIS, Species.VENIPEDE, Species.BUDEW, Species.KOFFING, Species.STUNKY, Species.CROAGUNK, Species.NIDORAN_F], - [TrainerPoolTier.UNCOMMON]: [Species.GALAR_SLOWPOKE, Species.SKORUPI, Species.PALDEA_WOOPER, Species.VULLABY, Species.HISUI_QWILFISH, Species.GLIMMET], - [TrainerPoolTier.RARE]: [Species.SKRELP, Species.HISUI_SNEASEL] - }; - } - case "macro": { - return { - [TrainerPoolTier.COMMON]: [ Species.HATENNA, Species.FEEBAS, Species.BOUNSWEET, Species.SALANDIT, Species.GALAR_PONYTA, Species.GOTHITA, Species.FROSLASS, Species.VULPIX, Species.FRILLISH, Species.ODDISH, Species.SINISTEA], - [TrainerPoolTier.UNCOMMON]: [Species.VULLABY, Species.MAREANIE, Species.ALOLA_VULPIX, Species.TOGEPI, Species.GALAR_CORSOLA, Species.APPLIN], - [TrainerPoolTier.RARE]: [Species.TINKATINK, Species.HISUI_LILLIGANT] - }; - } - case "star_1": { - return { - [TrainerPoolTier.COMMON]: [ Species.MURKROW, Species.SEEDOT, Species.CACNEA, Species.STUNKY, Species.SANDILE, Species.NYMBLE, Species.MASCHIFF, Species.GALAR_ZIGZAGOON ], - [TrainerPoolTier.UNCOMMON]: [ Species.UMBREON, Species.SNEASEL, Species.CORPHISH, Species.ZORUA, Species.INKAY, Species.BOMBIRDIER ], - [TrainerPoolTier.RARE]: [ Species.DEINO, Species.SPRIGATITO ] - }; - } - case "star_2": { - return { - [TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.HOUNDOUR, Species.NUMEL, Species.LITWICK, Species.FLETCHLING, Species.LITLEO, Species.ROLYCOLY, Species.CAPSAKID ], - [TrainerPoolTier.UNCOMMON]: [ Species.PONYTA, Species.FLAREON, Species.MAGBY, Species.TORKOAL, Species.SALANDIT, Species.TURTONATOR ], - [TrainerPoolTier.RARE]: [ Species.LARVESTA, Species.FUECOCO ] - }; - } - case "star_3": { - return { - [TrainerPoolTier.COMMON]: [ Species.ZUBAT, Species.GRIMER, Species.STUNKY, Species.FOONGUS, Species.MAREANIE, Species.TOXEL, Species.SHROODLE, Species.PALDEA_WOOPER ], - [TrainerPoolTier.UNCOMMON]: [ Species.GASTLY, Species.SEVIPER, Species.SKRELP, Species.ALOLA_GRIMER, Species.GALAR_SLOWPOKE, Species.HISUI_QWILFISH ], - [TrainerPoolTier.RARE]: [ Species.GLIMMET, Species.BULBASAUR ] - }; - } - case "star_4": { - return { - [TrainerPoolTier.COMMON]: [ Species.CLEFFA, Species.IGGLYBUFF, Species.AZURILL, Species.COTTONEE, Species.FLABEBE, Species.HATENNA, Species.IMPIDIMP, Species.TINKATINK ], - [TrainerPoolTier.UNCOMMON]: [ Species.TOGEPI, Species.GARDEVOIR, Species.SYLVEON, Species.KLEFKI, Species.MIMIKYU, Species.ALOLA_VULPIX ], - [TrainerPoolTier.RARE]: [ Species.GALAR_PONYTA, Species.POPPLIO ] - }; - } - case "star_5": { - return { - [TrainerPoolTier.COMMON]: [ Species.SHROOMISH, Species.MAKUHITA, Species.MEDITITE, Species.CROAGUNK, Species.SCRAGGY, Species.MIENFOO, Species.PAWMI, Species.PALDEA_TAUROS ], - [TrainerPoolTier.UNCOMMON]: [ Species.RIOLU, Species.TIMBURR, Species.HAWLUCHA, Species.PASSIMIAN, Species.FALINKS, Species.FLAMIGO ], - [TrainerPoolTier.RARE]: [ Species.JANGMO_O, Species.QUAXLY ] - }; - } + case "rocket": { + return { + [TrainerPoolTier.COMMON]: [ Species.RATTATA, Species.KOFFING, Species.EKANS, Species.ZUBAT, Species.MAGIKARP, Species.HOUNDOUR, Species.ONIX, Species.CUBONE, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB, Species.DROWZEE, Species.VILEPLUME ], + [TrainerPoolTier.UNCOMMON]: [ Species.PORYGON, Species.MANKEY, Species.MAGNEMITE, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE, Species.PALDEA_TAUROS, Species.OMANYTE, Species.KABUTO, Species.MAGBY, Species.ELEKID ], + [TrainerPoolTier.RARE]: [ Species.DRATINI, Species.LARVITAR ] + }; + } + case "magma": { + return { + [TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.SLUGMA, Species.SOLROCK, Species.HIPPOPOTAS, Species.BALTOY, Species.ROLYCOLY, Species.GLIGAR, Species.TORKOAL, Species.HOUNDOUR, Species.MAGBY ], + [TrainerPoolTier.UNCOMMON]: [ Species.TRAPINCH, Species.SILICOBRA, Species.RHYHORN, Species.ANORITH, Species.LILEEP, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON, Species.TOEDSCOOL ], + [TrainerPoolTier.RARE]: [ Species.CAPSAKID, Species.CHARCADET ] + }; + } + case "aqua": { + return { + [TrainerPoolTier.COMMON]: [ Species.CORPHISH, Species.SPHEAL, Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.AZURILL, Species.LOTAD, Species.WAILMER, Species.REMORAID, Species.BARBOACH ], + [TrainerPoolTier.UNCOMMON]: [ Species.MANTYKE, Species.HISUI_QWILFISH, Species.ARROKUDA, Species.DHELMISE, Species.CLOBBOPUS, Species.FEEBAS, Species.PALDEA_WOOPER, Species.HORSEA, Species.SKRELP ], + [TrainerPoolTier.RARE]: [ Species.DONDOZO, Species.BASCULEGION ] + }; + } + case "galactic": { + return { + [TrainerPoolTier.COMMON]: [ Species.BRONZOR, Species.SWINUB, Species.YANMA, Species.LICKITUNG, Species.TANGELA, Species.MAGBY, Species.ELEKID, Species.SKORUPI, Species.ZUBAT, Species.MURKROW, Species.MAGIKARP, Species.VOLTORB ], + [TrainerPoolTier.UNCOMMON]: [ Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.SNEASEL, Species.DUSKULL, Species.ROTOM, Species.HISUI_VOLTORB, Species.GLIGAR, Species.ABRA ], + [TrainerPoolTier.RARE]: [ Species.URSALUNA, Species.HISUI_LILLIGANT, Species.SPIRITOMB, Species.HISUI_SNEASEL ] + }; + } + case "plasma": { + return { + [TrainerPoolTier.COMMON]: [ Species.YAMASK, Species.ROGGENROLA, Species.JOLTIK, Species.TYMPOLE, Species.FRILLISH, Species.FERROSEED, Species.SANDILE, Species.TIMBURR, Species.DARUMAKA, Species.FOONGUS, Species.CUBCHOO, Species.VANILLITE ], + [TrainerPoolTier.UNCOMMON]: [ Species.PAWNIARD, Species.VULLABY, Species.ZORUA, Species.DRILBUR, Species.KLINK, Species.TYNAMO, Species.GALAR_DARUMAKA, Species.GOLETT, Species.MIENFOO, Species.DURANT, Species.SIGILYPH ], + [TrainerPoolTier.RARE]: [ Species.HISUI_ZORUA, Species.AXEW, Species.DEINO, Species.HISUI_BRAVIARY ] + }; + } + case "flare": { + return { + [TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.INKAY, Species.FOONGUS, Species.HELIOPTILE, Species.ELECTRIKE, Species.SKORUPI, Species.PURRLOIN, Species.CLAWITZER, Species.PANCHAM, Species.ESPURR, Species.BUNNELBY ], + [TrainerPoolTier.UNCOMMON]: [ Species.LITWICK, Species.SNEASEL, Species.PUMPKABOO, Species.PHANTUMP, Species.HONEDGE, Species.BINACLE, Species.HOUNDOUR, Species.SKRELP, Species.SLIGGOO ], + [TrainerPoolTier.RARE]: [ Species.NOIBAT, Species.HISUI_AVALUGG, Species.HISUI_SLIGGOO ] + }; + } + case "aether": { + return { + [TrainerPoolTier.COMMON]: [ Species.BRUXISH, Species.SLOWPOKE, Species.BALTOY, Species.EXEGGCUTE, Species.ABRA, Species.ALOLA_RAICHU, Species.ELGYEM, Species.NATU, Species.BLIPBUG, Species.GIRAFARIG, Species.ORANGURU ], + [TrainerPoolTier.UNCOMMON]: [ Species.GALAR_SLOWPOKE, Species.MEDITITE, Species.BELDUM, Species.HATENNA, Species.INKAY, Species.RALTS, Species.GALAR_MR_MIME ], + [TrainerPoolTier.RARE]: [ Species.ARMAROUGE, Species.HISUI_BRAVIARY, Species.PORYGON ] + }; + } + case "skull": { + return { + [TrainerPoolTier.COMMON]: [ Species.MAREANIE, Species.ALOLA_GRIMER, Species.GASTLY, Species.ZUBAT, Species.FOMANTIS, Species.VENIPEDE, Species.BUDEW, Species.KOFFING, Species.STUNKY, Species.CROAGUNK, Species.NIDORAN_F ], + [TrainerPoolTier.UNCOMMON]: [ Species.GALAR_SLOWPOKE, Species.SKORUPI, Species.PALDEA_WOOPER, Species.VULLABY, Species.HISUI_QWILFISH, Species.GLIMMET ], + [TrainerPoolTier.RARE]: [ Species.SKRELP, Species.HISUI_SNEASEL ] + }; + } + case "macro": { + return { + [TrainerPoolTier.COMMON]: [ Species.HATENNA, Species.FEEBAS, Species.BOUNSWEET, Species.SALANDIT, Species.GALAR_PONYTA, Species.GOTHITA, Species.FROSLASS, Species.VULPIX, Species.FRILLISH, Species.ODDISH, Species.SINISTEA ], + [TrainerPoolTier.UNCOMMON]: [ Species.VULLABY, Species.MAREANIE, Species.ALOLA_VULPIX, Species.TOGEPI, Species.GALAR_CORSOLA, Species.APPLIN ], + [TrainerPoolTier.RARE]: [ Species.TINKATINK, Species.HISUI_LILLIGANT ] + }; + } + case "star_1": { + return { + [TrainerPoolTier.COMMON]: [ Species.MURKROW, Species.SEEDOT, Species.CACNEA, Species.STUNKY, Species.SANDILE, Species.NYMBLE, Species.MASCHIFF, Species.GALAR_ZIGZAGOON ], + [TrainerPoolTier.UNCOMMON]: [ Species.UMBREON, Species.SNEASEL, Species.CORPHISH, Species.ZORUA, Species.INKAY, Species.BOMBIRDIER ], + [TrainerPoolTier.RARE]: [ Species.DEINO, Species.SPRIGATITO ] + }; + } + case "star_2": { + return { + [TrainerPoolTier.COMMON]: [ Species.GROWLITHE, Species.HOUNDOUR, Species.NUMEL, Species.LITWICK, Species.FLETCHLING, Species.LITLEO, Species.ROLYCOLY, Species.CAPSAKID ], + [TrainerPoolTier.UNCOMMON]: [ Species.PONYTA, Species.FLAREON, Species.MAGBY, Species.TORKOAL, Species.SALANDIT, Species.TURTONATOR ], + [TrainerPoolTier.RARE]: [ Species.LARVESTA, Species.FUECOCO ] + }; + } + case "star_3": { + return { + [TrainerPoolTier.COMMON]: [ Species.ZUBAT, Species.GRIMER, Species.STUNKY, Species.FOONGUS, Species.MAREANIE, Species.TOXEL, Species.SHROODLE, Species.PALDEA_WOOPER ], + [TrainerPoolTier.UNCOMMON]: [ Species.GASTLY, Species.SEVIPER, Species.SKRELP, Species.ALOLA_GRIMER, Species.GALAR_SLOWPOKE, Species.HISUI_QWILFISH ], + [TrainerPoolTier.RARE]: [ Species.GLIMMET, Species.BULBASAUR ] + }; + } + case "star_4": { + return { + [TrainerPoolTier.COMMON]: [ Species.CLEFFA, Species.IGGLYBUFF, Species.AZURILL, Species.COTTONEE, Species.FLABEBE, Species.HATENNA, Species.IMPIDIMP, Species.TINKATINK ], + [TrainerPoolTier.UNCOMMON]: [ Species.TOGEPI, Species.GARDEVOIR, Species.SYLVEON, Species.KLEFKI, Species.MIMIKYU, Species.ALOLA_VULPIX ], + [TrainerPoolTier.RARE]: [ Species.GALAR_PONYTA, Species.POPPLIO ] + }; + } + case "star_5": { + return { + [TrainerPoolTier.COMMON]: [ Species.SHROOMISH, Species.MAKUHITA, Species.MEDITITE, Species.CROAGUNK, Species.SCRAGGY, Species.MIENFOO, Species.PAWMI, Species.PALDEA_TAUROS ], + [TrainerPoolTier.UNCOMMON]: [ Species.RIOLU, Species.TIMBURR, Species.HAWLUCHA, Species.PASSIMIAN, Species.FALINKS, Species.FLAMIGO ], + [TrainerPoolTier.RARE]: [ Species.JANGMO_O, Species.QUAXLY ] + }; + } } console.warn(`Evil team admin for ${team} not found. Returning empty species pools.`); @@ -686,7 +686,7 @@ export class TrainerConfig { signatureSpecies.forEach((speciesPool, s) => { if (!Array.isArray(speciesPool)) { - speciesPool = [speciesPool]; + speciesPool = [ speciesPool ]; } this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); }); @@ -720,7 +720,7 @@ export class TrainerConfig { signatureSpecies.forEach((speciesPool, s) => { if (!Array.isArray(speciesPool)) { - speciesPool = [speciesPool]; + speciesPool = [ speciesPool ]; } this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); }); @@ -759,7 +759,7 @@ export class TrainerConfig { } signatureSpecies.forEach((speciesPool, s) => { if (!Array.isArray(speciesPool)) { - speciesPool = [speciesPool]; + speciesPool = [ speciesPool ]; } this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); }); @@ -800,7 +800,7 @@ export class TrainerConfig { signatureSpecies.forEach((speciesPool, s) => { // Ensure speciesPool is an array. if (!Array.isArray(speciesPool)) { - speciesPool = [speciesPool]; + speciesPool = [ speciesPool ]; } // Set a function to get a random party member from the species pool. this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); @@ -857,7 +857,7 @@ export class TrainerConfig { signatureSpecies.forEach((speciesPool, s) => { // Ensure speciesPool is an array. if (!Array.isArray(speciesPool)) { - speciesPool = [speciesPool]; + speciesPool = [ speciesPool ]; } // Set a function to get a random party member from the species pool. this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); @@ -912,7 +912,7 @@ export class TrainerConfig { signatureSpecies.forEach((speciesPool, s) => { // Ensure speciesPool is an array. if (!Array.isArray(speciesPool)) { - speciesPool = [speciesPool]; + speciesPool = [ speciesPool ]; } // Set a function to get a random party member from the species pool. this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(speciesPool)); @@ -1180,7 +1180,7 @@ function getRandomTeraModifiers(party: EnemyPokemon[], count: integer, types?: T for (let t = 0; t < Math.min(count, party.length); t++) { const randomIndex = Utils.randSeedItem(partyMemberIndexes); partyMemberIndexes.splice(partyMemberIndexes.indexOf(randomIndex), 1); - ret.push(modifierTypes.TERA_SHARD().generateType([], [Utils.randSeedItem(types ? types : party[randomIndex].getTypes())])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); // TODO: is the bang correct? + ret.push(modifierTypes.TERA_SHARD().generateType([], [ Utils.randSeedItem(types ? types : party[randomIndex].getTypes()) ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); // TODO: is the bang correct? } return ret; } @@ -1195,135 +1195,135 @@ type SignatureSpecies = { * This is in a separate const so it can be accessed from other places and not just the trainerConfigs */ export const signatureSpecies: SignatureSpecies = { - BROCK: [Species.GEODUDE, Species.ONIX], - MISTY: [Species.STARYU, Species.PSYDUCK], - LT_SURGE: [Species.VOLTORB, Species.PIKACHU, Species.ELECTABUZZ], - ERIKA: [Species.ODDISH, Species.BELLSPROUT, Species.TANGELA, Species.HOPPIP], - JANINE: [Species.VENONAT, Species.SPINARAK, Species.ZUBAT], - SABRINA: [Species.ABRA, Species.MR_MIME, Species.ESPEON], - BLAINE: [Species.GROWLITHE, Species.PONYTA, Species.MAGMAR], - GIOVANNI: [Species.SANDILE, Species.MURKROW, Species.NIDORAN_M, Species.NIDORAN_F], - FALKNER: [Species.PIDGEY, Species.HOOTHOOT, Species.DODUO], - BUGSY: [Species.SCYTHER, Species.HERACROSS, Species.SHUCKLE, Species.PINSIR], - WHITNEY: [Species.GIRAFARIG, Species.MILTANK], - MORTY: [Species.GASTLY, Species.MISDREAVUS, Species.SABLEYE], - CHUCK: [Species.POLIWRATH, Species.MANKEY], - JASMINE: [Species.MAGNEMITE, Species.STEELIX], - PRYCE: [Species.SEEL, Species.SWINUB], - CLAIR: [Species.DRATINI, Species.HORSEA, Species.GYARADOS], - ROXANNE: [Species.GEODUDE, Species.NOSEPASS], - BRAWLY: [Species.MACHOP, Species.MAKUHITA], - WATTSON: [Species.MAGNEMITE, Species.VOLTORB, Species.ELECTRIKE], - FLANNERY: [Species.SLUGMA, Species.TORKOAL, Species.NUMEL], - NORMAN: [Species.SLAKOTH, Species.SPINDA, Species.CHANSEY, Species.KANGASKHAN], - WINONA: [Species.SWABLU, Species.WINGULL, Species.TROPIUS, Species.SKARMORY], - TATE: [Species.SOLROCK, Species.NATU, Species.CHIMECHO, Species.GALLADE], - LIZA: [Species.LUNATONE, Species.SPOINK, Species.BALTOY, Species.GARDEVOIR], - JUAN: [Species.HORSEA, Species.BARBOACH, Species.SPHEAL, Species.RELICANTH], - ROARK: [Species.CRANIDOS, Species.LARVITAR, Species.GEODUDE], - GARDENIA: [Species.ROSELIA, Species.TANGELA, Species.TURTWIG], - MAYLENE: [Species.LUCARIO, Species.MEDITITE, Species.CHIMCHAR], - CRASHER_WAKE: [Species.BUIZEL, Species.MAGIKARP, Species.PIPLUP], - FANTINA: [Species.MISDREAVUS, Species.DRIFLOON, Species.SPIRITOMB], - BYRON: [Species.SHIELDON, Species.BRONZOR, Species.AGGRON], - CANDICE: [Species.SNEASEL, Species.SNOVER, Species.SNORUNT], - VOLKNER: [Species.SHINX, Species.CHINCHOU, Species.ROTOM], - CILAN: [Species.PANSAGE, Species.COTTONEE, Species.PETILIL], - CHILI: [Species.PANSEAR, Species.DARUMAKA, Species.HEATMOR], - CRESS: [Species.PANPOUR, Species.BASCULIN, Species.TYMPOLE], - CHEREN: [Species.LILLIPUP, Species.MINCCINO, Species.PATRAT], - LENORA: [Species.KANGASKHAN, Species.DEERLING, Species.AUDINO], - ROXIE: [Species.VENIPEDE, Species.TRUBBISH, Species.SKORUPI], - BURGH: [Species.SEWADDLE, Species.SHELMET, Species.KARRABLAST], - ELESA: [Species.EMOLGA, Species.BLITZLE, Species.JOLTIK], - CLAY: [Species.DRILBUR, Species.SANDILE, Species.GOLETT], - SKYLA: [Species.DUCKLETT, Species.WOOBAT, Species.RUFFLET], - BRYCEN: [Species.CRYOGONAL, Species.VANILLITE, Species.CUBCHOO], - DRAYDEN: [Species.DRUDDIGON, Species.AXEW, Species.DEINO], - MARLON: [Species.WAILMER, Species.FRILLISH, Species.TIRTOUGA], - VIOLA: [Species.SURSKIT, Species.SCATTERBUG], - GRANT: [Species.AMAURA, Species.TYRUNT], - KORRINA: [Species.HAWLUCHA, Species.LUCARIO, Species.MIENFOO], - RAMOS: [Species.SKIDDO, Species.HOPPIP, Species.BELLSPROUT], - CLEMONT: [Species.HELIOPTILE, Species.MAGNEMITE, Species.EMOLGA], - VALERIE: [Species.SYLVEON, Species.MAWILE, Species.MR_MIME], - OLYMPIA: [Species.ESPURR, Species.SIGILYPH, Species.SLOWKING], - WULFRIC: [Species.BERGMITE, Species.SNOVER, Species.CRYOGONAL], - MILO: [Species.GOSSIFLEUR, Species.APPLIN, Species.BOUNSWEET], - NESSA: [Species.CHEWTLE, Species.ARROKUDA, Species.WIMPOD], - KABU: [Species.SIZZLIPEDE, Species.VULPIX, Species.TORKOAL], - BEA: [Species.GALAR_FARFETCHD, Species.MACHOP, Species.CLOBBOPUS], - ALLISTER: [Species.GALAR_YAMASK, Species.GALAR_CORSOLA, Species.GASTLY], - OPAL: [Species.MILCERY, Species.TOGETIC, Species.GALAR_WEEZING], - BEDE: [Species.HATENNA, Species.GALAR_PONYTA, Species.GARDEVOIR], - GORDIE: [Species.ROLYCOLY, Species.STONJOURNER, Species.BINACLE], - MELONY: [Species.SNOM, Species.GALAR_DARUMAKA, Species.GALAR_MR_MIME], - PIERS: [Species.GALAR_ZIGZAGOON, Species.SCRAGGY, Species.INKAY], - MARNIE: [Species.IMPIDIMP, Species.PURRLOIN, Species.MORPEKO], - RAIHAN: [Species.DURALUDON, Species.TURTONATOR, Species.GOOMY], - KATY: [Species.NYMBLE, Species.TAROUNTULA, Species.HERACROSS], - BRASSIUS: [Species.SMOLIV, Species.SHROOMISH, Species.ODDISH], - IONO: [Species.TADBULB, Species.WATTREL, Species.VOLTORB], - KOFU: [Species.VELUZA, Species.WIGLETT, Species.WINGULL], - LARRY: [Species.STARLY, Species.DUNSPARCE, Species.KOMALA], - RYME: [Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], - TULIP: [Species.GIRAFARIG, Species.FLITTLE, Species.RALTS], - GRUSHA: [Species.CETODDLE, Species.ALOLA_VULPIX, Species.CUBCHOO], - LORELEI: [Species.JYNX, [Species.SLOWBRO, Species.GALAR_SLOWBRO], Species.LAPRAS, [Species.ALOLA_SANDSLASH, Species.CLOYSTER]], - BRUNO: [Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [Species.ALOLA_GOLEM, Species.GOLEM]], - AGATHA: [Species.GENGAR, [Species.ARBOK, Species.WEEZING], Species.CROBAT, Species.ALOLA_MAROWAK], - LANCE: [Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR], - WILL: [Species.XATU, Species.JYNX, [Species.SLOWBRO, Species.SLOWKING], Species.EXEGGUTOR], - KOGA: [[Species.WEEZING, Species.MUK], [Species.VENOMOTH, Species.ARIADOS], Species.CROBAT, Species.TENTACRUEL], - KAREN: [Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE], - SIDNEY: [[Species.SHIFTRY, Species.CACTURNE], [Species.SHARPEDO, Species.CRAWDAUNT], Species.ABSOL, Species.MIGHTYENA], - PHOEBE: [Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [Species.MISMAGIUS, Species.DRIFBLIM]], - GLACIA: [Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW], - DRAKE: [Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA], - AARON: [[Species.SCIZOR, Species.KLEAVOR], Species.HERACROSS, [Species.VESPIQUEN, Species.YANMEGA], Species.DRAPION], - BERTHA: [Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR], - FLINT: [[Species.FLAREON, Species.RAPIDASH], Species.MAGMORTAR, [Species.STEELIX, Species.LOPUNNY], Species.INFERNAPE], - LUCIAN: [Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [Species.ALAKAZAM, Species.ESPEON]], - SHAUNTAL: [Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT], - MARSHAL: [Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK], - GRIMSLEY: [Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE], - CAITLIN: [Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS], - MALVA: [Species.PYROAR, Species.TORKOAL, Species.CHANDELURE, Species.TALONFLAME], - SIEBOLD: [Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE], - WIKSTROM: [Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH], - DRASNA: [Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN], - HALA: [Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [Species.POLIWRATH, Species.ANNIHILAPE]], - MOLAYNE: [Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO], - OLIVIA: [Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC], - ACEROLA: [[Species.BANETTE, Species.DRIFBLIM], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND], - KAHILI: [[Species.BRAVIARY, Species.MANDIBUZZ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON], - MARNIE_ELITE: [Species.MORPEKO, Species.LIEPARD, [Species.TOXICROAK, Species.SCRAFTY], Species.GRIMMSNARL], - NESSA_ELITE: [Species.GOLISOPOD, [Species.PELIPPER, Species.QUAGSIRE], Species.TOXAPEX, Species.DREDNAW], - BEA_ELITE: [Species.HAWLUCHA, [Species.GRAPPLOCT, Species.SIRFETCHD], Species.FALINKS, Species.MACHAMP], - ALLISTER_ELITE: [Species.DUSKNOIR, [Species.POLTEAGEIST, Species.RUNERIGUS], Species.CURSOLA, Species.GENGAR], - RAIHAN_ELITE: [Species.GOODRA, [Species.TORKOAL, Species.TURTONATOR], Species.FLYGON, Species.ARCHALUDON], - RIKA: [Species.WHISCASH, [Species.DONPHAN, Species.DUGTRIO], Species.CAMERUPT, Species.CLODSIRE], - POPPY: [Species.COPPERAJAH, Species.BRONZONG, Species.CORVIKNIGHT, Species.TINKATON], - LARRY_ELITE: [Species.STARAPTOR, Species.FLAMIGO, Species.ALTARIA, Species.TROPIUS], - HASSEL: [Species.NOIVERN, [Species.FLAPPLE, Species.APPLETUN], Species.DRAGALGE, Species.BAXCALIBUR], - CRISPIN: [Species.TALONFLAME, Species.CAMERUPT, Species.MAGMORTAR, Species.BLAZIKEN], - AMARYS: [Species.SKARMORY, Species.EMPOLEON, Species.SCIZOR, Species.METAGROSS], - LACEY: [Species.EXCADRILL, Species.PRIMARINA, [Species.ALCREMIE, Species.GRANBULL], Species.WHIMSICOTT], - DRAYTON: [Species.DRAGONITE, Species.ARCHALUDON, Species.HAXORUS, Species.SCEPTILE], - BLUE: [[Species.GYARADOS, Species.EXEGGUTOR, Species.ARCANINE], Species.HO_OH, [Species.RHYPERIOR, Species.MAGNEZONE]], // Alakazam lead, Mega Pidgeot - RED: [Species.LUGIA, Species.SNORLAX, [Species.ESPEON, Species.UMBREON, Species.SYLVEON]], // GMax Pikachu lead, Mega gen 1 starter - LANCE_CHAMPION: [Species.DRAGONITE, Species.KINGDRA, Species.ALOLA_EXEGGUTOR], // Aerodactyl lead, Mega Latias/Latios - STEVEN: [Species.AGGRON, [Species.ARMALDO, Species.CRADILY], Species.DIALGA], // Skarmory lead, Mega Metagross - WALLACE: [Species.MILOTIC, Species.PALKIA, Species.LUDICOLO], // Pelipper lead, Mega Swampert - CYNTHIA: [Species.GIRATINA, Species.LUCARIO, Species.TOGEKISS], // Spiritomb lead, Mega Garchomp - ALDER: [Species.VOLCARONA, Species.ZEKROM, [Species.ACCELGOR, Species.ESCAVALIER], Species.KELDEO], // Bouffalant/Braviary lead - IRIS: [Species.HAXORUS, Species.RESHIRAM, Species.ARCHEOPS], // Druddigon lead, Gmax Lapras - DIANTHA: [Species.HAWLUCHA, Species.XERNEAS, Species.GOODRA], // Gourgeist lead, Mega Gardevoir - HAU: [[Species.SOLGALEO, Species.LUNALA], Species.NOIVERN, [Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA], [Species.TAPU_BULU, Species.TAPU_FINI, Species.TAPU_KOKO, Species.TAPU_LELE]], // Alola Raichu lead - LEON: [Species.DRAGAPULT, Species.ZACIAN, Species.AEGISLASH], // Rillaboom/Cinderace/Inteleon lead, GMax Charizard - GEETA: [Species.MIRAIDON, [Species.ESPATHRA, Species.VELUZA], [Species.AVALUGG, Species.HISUI_AVALUGG], Species.KINGAMBIT], // Glimmora lead - NEMONA: [Species.KORAIDON, Species.PAWMOT, [Species.DUDUNSPARCE, Species.ORTHWORM], [Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL]], // Lycanroc lead - KIERAN: [[Species.GRIMMSNARL, Species.INCINEROAR, Species.PORYGON_Z], Species.OGERPON, Species.TERAPAGOS, Species.HYDRAPPLE], // Poliwrath/Politoed lead + BROCK: [ Species.GEODUDE, Species.ONIX ], + MISTY: [ Species.STARYU, Species.PSYDUCK ], + LT_SURGE: [ Species.VOLTORB, Species.PIKACHU, Species.ELECTABUZZ ], + ERIKA: [ Species.ODDISH, Species.BELLSPROUT, Species.TANGELA, Species.HOPPIP ], + JANINE: [ Species.VENONAT, Species.SPINARAK, Species.ZUBAT ], + SABRINA: [ Species.ABRA, Species.MR_MIME, Species.ESPEON ], + BLAINE: [ Species.GROWLITHE, Species.PONYTA, Species.MAGMAR ], + GIOVANNI: [ Species.SANDILE, Species.MURKROW, Species.NIDORAN_M, Species.NIDORAN_F ], + FALKNER: [ Species.PIDGEY, Species.HOOTHOOT, Species.DODUO ], + BUGSY: [ Species.SCYTHER, Species.HERACROSS, Species.SHUCKLE, Species.PINSIR ], + WHITNEY: [ Species.GIRAFARIG, Species.MILTANK ], + MORTY: [ Species.GASTLY, Species.MISDREAVUS, Species.SABLEYE ], + CHUCK: [ Species.POLIWRATH, Species.MANKEY ], + JASMINE: [ Species.MAGNEMITE, Species.STEELIX ], + PRYCE: [ Species.SEEL, Species.SWINUB ], + CLAIR: [ Species.DRATINI, Species.HORSEA, Species.GYARADOS ], + ROXANNE: [ Species.GEODUDE, Species.NOSEPASS ], + BRAWLY: [ Species.MACHOP, Species.MAKUHITA ], + WATTSON: [ Species.MAGNEMITE, Species.VOLTORB, Species.ELECTRIKE ], + FLANNERY: [ Species.SLUGMA, Species.TORKOAL, Species.NUMEL ], + NORMAN: [ Species.SLAKOTH, Species.SPINDA, Species.CHANSEY, Species.KANGASKHAN ], + WINONA: [ Species.SWABLU, Species.WINGULL, Species.TROPIUS, Species.SKARMORY ], + TATE: [ Species.SOLROCK, Species.NATU, Species.CHIMECHO, Species.GALLADE ], + LIZA: [ Species.LUNATONE, Species.SPOINK, Species.BALTOY, Species.GARDEVOIR ], + JUAN: [ Species.HORSEA, Species.BARBOACH, Species.SPHEAL, Species.RELICANTH ], + ROARK: [ Species.CRANIDOS, Species.LARVITAR, Species.GEODUDE ], + GARDENIA: [ Species.ROSELIA, Species.TANGELA, Species.TURTWIG ], + MAYLENE: [ Species.LUCARIO, Species.MEDITITE, Species.CHIMCHAR ], + CRASHER_WAKE: [ Species.BUIZEL, Species.MAGIKARP, Species.PIPLUP ], + FANTINA: [ Species.MISDREAVUS, Species.DRIFLOON, Species.SPIRITOMB ], + BYRON: [ Species.SHIELDON, Species.BRONZOR, Species.AGGRON ], + CANDICE: [ Species.SNEASEL, Species.SNOVER, Species.SNORUNT ], + VOLKNER: [ Species.SHINX, Species.CHINCHOU, Species.ROTOM ], + CILAN: [ Species.PANSAGE, Species.COTTONEE, Species.PETILIL ], + CHILI: [ Species.PANSEAR, Species.DARUMAKA, Species.HEATMOR ], + CRESS: [ Species.PANPOUR, Species.BASCULIN, Species.TYMPOLE ], + CHEREN: [ Species.LILLIPUP, Species.MINCCINO, Species.PATRAT ], + LENORA: [ Species.KANGASKHAN, Species.DEERLING, Species.AUDINO ], + ROXIE: [ Species.VENIPEDE, Species.TRUBBISH, Species.SKORUPI ], + BURGH: [ Species.SEWADDLE, Species.SHELMET, Species.KARRABLAST ], + ELESA: [ Species.EMOLGA, Species.BLITZLE, Species.JOLTIK ], + CLAY: [ Species.DRILBUR, Species.SANDILE, Species.GOLETT ], + SKYLA: [ Species.DUCKLETT, Species.WOOBAT, Species.RUFFLET ], + BRYCEN: [ Species.CRYOGONAL, Species.VANILLITE, Species.CUBCHOO ], + DRAYDEN: [ Species.DRUDDIGON, Species.AXEW, Species.DEINO ], + MARLON: [ Species.WAILMER, Species.FRILLISH, Species.TIRTOUGA ], + VIOLA: [ Species.SURSKIT, Species.SCATTERBUG ], + GRANT: [ Species.AMAURA, Species.TYRUNT ], + KORRINA: [ Species.HAWLUCHA, Species.LUCARIO, Species.MIENFOO ], + RAMOS: [ Species.SKIDDO, Species.HOPPIP, Species.BELLSPROUT ], + CLEMONT: [ Species.HELIOPTILE, Species.MAGNEMITE, Species.EMOLGA ], + VALERIE: [ Species.SYLVEON, Species.MAWILE, Species.MR_MIME ], + OLYMPIA: [ Species.ESPURR, Species.SIGILYPH, Species.SLOWKING ], + WULFRIC: [ Species.BERGMITE, Species.SNOVER, Species.CRYOGONAL ], + MILO: [ Species.GOSSIFLEUR, Species.APPLIN, Species.BOUNSWEET ], + NESSA: [ Species.CHEWTLE, Species.ARROKUDA, Species.WIMPOD ], + KABU: [ Species.SIZZLIPEDE, Species.VULPIX, Species.TORKOAL ], + BEA: [ Species.GALAR_FARFETCHD, Species.MACHOP, Species.CLOBBOPUS ], + ALLISTER: [ Species.GALAR_YAMASK, Species.GALAR_CORSOLA, Species.GASTLY ], + OPAL: [ Species.MILCERY, Species.TOGETIC, Species.GALAR_WEEZING ], + BEDE: [ Species.HATENNA, Species.GALAR_PONYTA, Species.GARDEVOIR ], + GORDIE: [ Species.ROLYCOLY, Species.STONJOURNER, Species.BINACLE ], + MELONY: [ Species.SNOM, Species.GALAR_DARUMAKA, Species.GALAR_MR_MIME ], + PIERS: [ Species.GALAR_ZIGZAGOON, Species.SCRAGGY, Species.INKAY ], + MARNIE: [ Species.IMPIDIMP, Species.PURRLOIN, Species.MORPEKO ], + RAIHAN: [ Species.DURALUDON, Species.TURTONATOR, Species.GOOMY ], + KATY: [ Species.NYMBLE, Species.TAROUNTULA, Species.HERACROSS ], + BRASSIUS: [ Species.SMOLIV, Species.SHROOMISH, Species.ODDISH ], + IONO: [ Species.TADBULB, Species.WATTREL, Species.VOLTORB ], + KOFU: [ Species.VELUZA, Species.WIGLETT, Species.WINGULL ], + LARRY: [ Species.STARLY, Species.DUNSPARCE, Species.KOMALA ], + RYME: [ Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU ], + TULIP: [ Species.GIRAFARIG, Species.FLITTLE, Species.RALTS ], + GRUSHA: [ Species.CETODDLE, Species.ALOLA_VULPIX, Species.CUBCHOO ], + LORELEI: [ Species.JYNX, [ Species.SLOWBRO, Species.GALAR_SLOWBRO ], Species.LAPRAS, [ Species.ALOLA_SANDSLASH, Species.CLOYSTER ]], + BRUNO: [ Species.MACHAMP, Species.HITMONCHAN, Species.HITMONLEE, [ Species.ALOLA_GOLEM, Species.GOLEM ]], + AGATHA: [ Species.GENGAR, [ Species.ARBOK, Species.WEEZING ], Species.CROBAT, Species.ALOLA_MAROWAK ], + LANCE: [ Species.DRAGONITE, Species.GYARADOS, Species.AERODACTYL, Species.ALOLA_EXEGGUTOR ], + WILL: [ Species.XATU, Species.JYNX, [ Species.SLOWBRO, Species.SLOWKING ], Species.EXEGGUTOR ], + KOGA: [[ Species.WEEZING, Species.MUK ], [ Species.VENOMOTH, Species.ARIADOS ], Species.CROBAT, Species.TENTACRUEL ], + KAREN: [ Species.UMBREON, Species.HONCHKROW, Species.HOUNDOOM, Species.WEAVILE ], + SIDNEY: [[ Species.SHIFTRY, Species.CACTURNE ], [ Species.SHARPEDO, Species.CRAWDAUNT ], Species.ABSOL, Species.MIGHTYENA ], + PHOEBE: [ Species.SABLEYE, Species.DUSKNOIR, Species.BANETTE, [ Species.MISMAGIUS, Species.DRIFBLIM ]], + GLACIA: [ Species.GLALIE, Species.WALREIN, Species.FROSLASS, Species.ABOMASNOW ], + DRAKE: [ Species.ALTARIA, Species.SALAMENCE, Species.FLYGON, Species.KINGDRA ], + AARON: [[ Species.SCIZOR, Species.KLEAVOR ], Species.HERACROSS, [ Species.VESPIQUEN, Species.YANMEGA ], Species.DRAPION ], + BERTHA: [ Species.WHISCASH, Species.HIPPOWDON, Species.GLISCOR, Species.RHYPERIOR ], + FLINT: [[ Species.FLAREON, Species.RAPIDASH ], Species.MAGMORTAR, [ Species.STEELIX, Species.LOPUNNY ], Species.INFERNAPE ], + LUCIAN: [ Species.MR_MIME, Species.GALLADE, Species.BRONZONG, [ Species.ALAKAZAM, Species.ESPEON ]], + SHAUNTAL: [ Species.COFAGRIGUS, Species.CHANDELURE, Species.GOLURK, Species.JELLICENT ], + MARSHAL: [ Species.CONKELDURR, Species.MIENSHAO, Species.THROH, Species.SAWK ], + GRIMSLEY: [ Species.LIEPARD, Species.KINGAMBIT, Species.SCRAFTY, Species.KROOKODILE ], + CAITLIN: [ Species.MUSHARNA, Species.GOTHITELLE, Species.SIGILYPH, Species.REUNICLUS ], + MALVA: [ Species.PYROAR, Species.TORKOAL, Species.CHANDELURE, Species.TALONFLAME ], + SIEBOLD: [ Species.CLAWITZER, Species.GYARADOS, Species.BARBARACLE, Species.STARMIE ], + WIKSTROM: [ Species.KLEFKI, Species.PROBOPASS, Species.SCIZOR, Species.AEGISLASH ], + DRASNA: [ Species.DRAGALGE, Species.DRUDDIGON, Species.ALTARIA, Species.NOIVERN ], + HALA: [ Species.HARIYAMA, Species.BEWEAR, Species.CRABOMINABLE, [ Species.POLIWRATH, Species.ANNIHILAPE ]], + MOLAYNE: [ Species.KLEFKI, Species.MAGNEZONE, Species.METAGROSS, Species.ALOLA_DUGTRIO ], + OLIVIA: [ Species.RELICANTH, Species.CARBINK, Species.ALOLA_GOLEM, Species.LYCANROC ], + ACEROLA: [[ Species.BANETTE, Species.DRIFBLIM ], Species.MIMIKYU, Species.DHELMISE, Species.PALOSSAND ], + KAHILI: [[ Species.BRAVIARY, Species.MANDIBUZZ ], Species.HAWLUCHA, Species.ORICORIO, Species.TOUCANNON ], + MARNIE_ELITE: [ Species.MORPEKO, Species.LIEPARD, [ Species.TOXICROAK, Species.SCRAFTY ], Species.GRIMMSNARL ], + NESSA_ELITE: [ Species.GOLISOPOD, [ Species.PELIPPER, Species.QUAGSIRE ], Species.TOXAPEX, Species.DREDNAW ], + BEA_ELITE: [ Species.HAWLUCHA, [ Species.GRAPPLOCT, Species.SIRFETCHD ], Species.FALINKS, Species.MACHAMP ], + ALLISTER_ELITE: [ Species.DUSKNOIR, [ Species.POLTEAGEIST, Species.RUNERIGUS ], Species.CURSOLA, Species.GENGAR ], + RAIHAN_ELITE: [ Species.GOODRA, [ Species.TORKOAL, Species.TURTONATOR ], Species.FLYGON, Species.ARCHALUDON ], + RIKA: [ Species.WHISCASH, [ Species.DONPHAN, Species.DUGTRIO ], Species.CAMERUPT, Species.CLODSIRE ], + POPPY: [ Species.COPPERAJAH, Species.BRONZONG, Species.CORVIKNIGHT, Species.TINKATON ], + LARRY_ELITE: [ Species.STARAPTOR, Species.FLAMIGO, Species.ALTARIA, Species.TROPIUS ], + HASSEL: [ Species.NOIVERN, [ Species.FLAPPLE, Species.APPLETUN ], Species.DRAGALGE, Species.BAXCALIBUR ], + CRISPIN: [ Species.TALONFLAME, Species.CAMERUPT, Species.MAGMORTAR, Species.BLAZIKEN ], + AMARYS: [ Species.SKARMORY, Species.EMPOLEON, Species.SCIZOR, Species.METAGROSS ], + LACEY: [ Species.EXCADRILL, Species.PRIMARINA, [ Species.ALCREMIE, Species.GRANBULL ], Species.WHIMSICOTT ], + DRAYTON: [ Species.DRAGONITE, Species.ARCHALUDON, Species.HAXORUS, Species.SCEPTILE ], + BLUE: [[ Species.GYARADOS, Species.EXEGGUTOR, Species.ARCANINE ], Species.HO_OH, [ Species.RHYPERIOR, Species.MAGNEZONE ]], // Alakazam lead, Mega Pidgeot + RED: [ Species.LUGIA, Species.SNORLAX, [ Species.ESPEON, Species.UMBREON, Species.SYLVEON ]], // GMax Pikachu lead, Mega gen 1 starter + LANCE_CHAMPION: [ Species.DRAGONITE, Species.KINGDRA, Species.ALOLA_EXEGGUTOR ], // Aerodactyl lead, Mega Latias/Latios + STEVEN: [ Species.AGGRON, [ Species.ARMALDO, Species.CRADILY ], Species.DIALGA ], // Skarmory lead, Mega Metagross + WALLACE: [ Species.MILOTIC, Species.PALKIA, Species.LUDICOLO ], // Pelipper lead, Mega Swampert + CYNTHIA: [ Species.GIRATINA, Species.LUCARIO, Species.TOGEKISS ], // Spiritomb lead, Mega Garchomp + ALDER: [ Species.VOLCARONA, Species.ZEKROM, [ Species.ACCELGOR, Species.ESCAVALIER ], Species.KELDEO ], // Bouffalant/Braviary lead + IRIS: [ Species.HAXORUS, Species.RESHIRAM, Species.ARCHEOPS ], // Druddigon lead, Gmax Lapras + DIANTHA: [ Species.HAWLUCHA, Species.XERNEAS, Species.GOODRA ], // Gourgeist lead, Mega Gardevoir + HAU: [[ Species.SOLGALEO, Species.LUNALA ], Species.NOIVERN, [ Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA ], [ Species.TAPU_BULU, Species.TAPU_FINI, Species.TAPU_KOKO, Species.TAPU_LELE ]], // Alola Raichu lead + LEON: [ Species.DRAGAPULT, Species.ZACIAN, Species.AEGISLASH ], // Rillaboom/Cinderace/Inteleon lead, GMax Charizard + GEETA: [ Species.MIRAIDON, [ Species.ESPATHRA, Species.VELUZA ], [ Species.AVALUGG, Species.HISUI_AVALUGG ], Species.KINGAMBIT ], // Glimmora lead + NEMONA: [ Species.KORAIDON, Species.PAWMOT, [ Species.DUDUNSPARCE, Species.ORTHWORM ], [ Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ]], // Lycanroc lead + KIERAN: [[ Species.GRIMMSNARL, Species.INCINEROAR, Species.PORYGON_Z ], Species.OGERPON, Species.TERAPAGOS, Species.HYDRAPPLE ], // Poliwrath/Politoed lead }; export const trainerConfigs: TrainerConfigs = { @@ -1331,15 +1331,15 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.ACE_TRAINER]: new TrainerConfig(++t).setHasGenders("Ace Trainer Female").setHasDouble("Ace Duo").setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.ACE_TRAINER) .setPartyTemplateFunc(scene => getWavePartyTemplate(scene, trainerPartyTemplates.THREE_WEAK_BALANCED, trainerPartyTemplates.FOUR_WEAK_BALANCED, trainerPartyTemplates.FIVE_WEAK_BALANCED, trainerPartyTemplates.SIX_WEAK_BALANCED)), [TrainerType.ARTIST]: new TrainerConfig(++t).setEncounterBgm(TrainerType.RICH).setPartyTemplates(trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.THREE_AVG) - .setSpeciesPools([Species.SMEARGLE]), + .setSpeciesPools([ Species.SMEARGLE ]), [TrainerType.BACKERS]: new TrainerConfig(++t).setHasGenders("Backers").setDoubleOnly().setEncounterBgm(TrainerType.CYCLIST), [TrainerType.BACKPACKER]: new TrainerConfig(++t).setHasGenders("Backpacker Female").setHasDouble("Backpackers").setSpeciesFilter(s => s.isOfType(Type.FLYING) || s.isOfType(Type.ROCK)).setEncounterBgm(TrainerType.BACKPACKER) .setPartyTemplates(trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.ONE_WEAK_ONE_STRONG, trainerPartyTemplates.ONE_AVG_ONE_STRONG) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.RHYHORN, Species.AIPOM, Species.MAKUHITA, Species.MAWILE, Species.NUMEL, Species.LILLIPUP, Species.SANDILE, Species.WOOLOO], - [TrainerPoolTier.UNCOMMON]: [Species.GIRAFARIG, Species.ZANGOOSE, Species.SEVIPER, Species.CUBCHOO, Species.PANCHAM, Species.SKIDDO, Species.MUDBRAY], - [TrainerPoolTier.RARE]: [Species.TAUROS, Species.STANTLER, Species.DARUMAKA, Species.BOUFFALANT, Species.DEERLING, Species.IMPIDIMP], - [TrainerPoolTier.SUPER_RARE]: [Species.GALAR_DARUMAKA, Species.TEDDIURSA] + [TrainerPoolTier.COMMON]: [ Species.RHYHORN, Species.AIPOM, Species.MAKUHITA, Species.MAWILE, Species.NUMEL, Species.LILLIPUP, Species.SANDILE, Species.WOOLOO ], + [TrainerPoolTier.UNCOMMON]: [ Species.GIRAFARIG, Species.ZANGOOSE, Species.SEVIPER, Species.CUBCHOO, Species.PANCHAM, Species.SKIDDO, Species.MUDBRAY ], + [TrainerPoolTier.RARE]: [ Species.TAUROS, Species.STANTLER, Species.DARUMAKA, Species.BOUFFALANT, Species.DEERLING, Species.IMPIDIMP ], + [TrainerPoolTier.SUPER_RARE]: [ Species.GALAR_DARUMAKA, Species.TEDDIURSA ] }), [TrainerType.BAKER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK).setMoneyMultiplier(1.35).setSpeciesFilter(s => s.isOfType(Type.GRASS) || s.isOfType(Type.FIRE)), [TrainerType.BEAUTY]: new TrainerConfig(++t).setMoneyMultiplier(1.55).setEncounterBgm(TrainerType.PARASOL_LADY), @@ -1347,11 +1347,11 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.BLACK_BELT]: new TrainerConfig(++t).setHasGenders("Battle Girl", TrainerType.PSYCHIC).setHasDouble("Crush Kin").setEncounterBgm(TrainerType.ROUGHNECK).setSpecialtyTypes(Type.FIGHTING) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK_ONE_AVG, trainerPartyTemplates.TWO_WEAK_ONE_AVG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_ONE_STRONG, trainerPartyTemplates.THREE_AVG, trainerPartyTemplates.TWO_AVG_ONE_STRONG) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.NIDORAN_F, Species.NIDORAN_M, Species.MACHOP, Species.MAKUHITA, Species.MEDITITE, Species.CROAGUNK, Species.TIMBURR], - [TrainerPoolTier.UNCOMMON]: [Species.MANKEY, Species.POLIWRATH, Species.TYROGUE, Species.BRELOOM, Species.SCRAGGY, Species.MIENFOO, Species.PANCHAM, Species.STUFFUL, Species.CRABRAWLER], - [TrainerPoolTier.RARE]: [Species.HERACROSS, Species.RIOLU, Species.THROH, Species.SAWK, Species.PASSIMIAN, Species.CLOBBOPUS], - [TrainerPoolTier.SUPER_RARE]: [Species.HITMONTOP, Species.INFERNAPE, Species.GALLADE, Species.HAWLUCHA, Species.HAKAMO_O], - [TrainerPoolTier.ULTRA_RARE]: [Species.KUBFU] + [TrainerPoolTier.COMMON]: [ Species.NIDORAN_F, Species.NIDORAN_M, Species.MACHOP, Species.MAKUHITA, Species.MEDITITE, Species.CROAGUNK, Species.TIMBURR ], + [TrainerPoolTier.UNCOMMON]: [ Species.MANKEY, Species.POLIWRATH, Species.TYROGUE, Species.BRELOOM, Species.SCRAGGY, Species.MIENFOO, Species.PANCHAM, Species.STUFFUL, Species.CRABRAWLER ], + [TrainerPoolTier.RARE]: [ Species.HERACROSS, Species.RIOLU, Species.THROH, Species.SAWK, Species.PASSIMIAN, Species.CLOBBOPUS ], + [TrainerPoolTier.SUPER_RARE]: [ Species.HITMONTOP, Species.INFERNAPE, Species.GALLADE, Species.HAWLUCHA, Species.HAKAMO_O ], + [TrainerPoolTier.ULTRA_RARE]: [ Species.KUBFU ] }), [TrainerType.BREEDER]: new TrainerConfig(++t).setMoneyMultiplier(1.325).setEncounterBgm(TrainerType.POKEFAN).setHasGenders("Breeder Female").setHasDouble("Breeders") .setPartyTemplateFunc(scene => getWavePartyTemplate(scene, trainerPartyTemplates.FOUR_WEAKER, trainerPartyTemplates.FIVE_WEAKER, trainerPartyTemplates.SIX_WEAKER)) @@ -1359,25 +1359,25 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.CLERK]: new TrainerConfig(++t).setHasGenders("Clerk Female").setHasDouble("Colleagues").setEncounterBgm(TrainerType.CLERK) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.THREE_WEAK, trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_ONE_AVG) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.MEOWTH, Species.PSYDUCK, Species.BUDEW, Species.PIDOVE, Species.CINCCINO, Species.LITLEO], - [TrainerPoolTier.UNCOMMON]: [Species.JIGGLYPUFF, Species.MAGNEMITE, Species.MARILL, Species.COTTONEE, Species.SKIDDO], - [TrainerPoolTier.RARE]: [Species.BUIZEL, Species.SNEASEL, Species.KLEFKI, Species.INDEEDEE] + [TrainerPoolTier.COMMON]: [ Species.MEOWTH, Species.PSYDUCK, Species.BUDEW, Species.PIDOVE, Species.CINCCINO, Species.LITLEO ], + [TrainerPoolTier.UNCOMMON]: [ Species.JIGGLYPUFF, Species.MAGNEMITE, Species.MARILL, Species.COTTONEE, Species.SKIDDO ], + [TrainerPoolTier.RARE]: [ Species.BUIZEL, Species.SNEASEL, Species.KLEFKI, Species.INDEEDEE ] }), [TrainerType.CYCLIST]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setHasGenders("Cyclist Female").setHasDouble("Cyclists").setEncounterBgm(TrainerType.CYCLIST) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.ONE_AVG) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.PICHU, Species.STARLY, Species.TAILLOW, Species.BOLTUND], - [TrainerPoolTier.UNCOMMON]: [Species.DODUO, Species.ELECTRIKE, Species.BLITZLE, Species.WATTREL], - [TrainerPoolTier.RARE]: [Species.YANMA, Species.NINJASK, Species.WHIRLIPEDE, Species.EMOLGA], - [TrainerPoolTier.SUPER_RARE]: [Species.ACCELGOR, Species.DREEPY] + [TrainerPoolTier.COMMON]: [ Species.PICHU, Species.STARLY, Species.TAILLOW, Species.BOLTUND ], + [TrainerPoolTier.UNCOMMON]: [ Species.DODUO, Species.ELECTRIKE, Species.BLITZLE, Species.WATTREL ], + [TrainerPoolTier.RARE]: [ Species.YANMA, Species.NINJASK, Species.WHIRLIPEDE, Species.EMOLGA ], + [TrainerPoolTier.SUPER_RARE]: [ Species.ACCELGOR, Species.DREEPY ] }), [TrainerType.DANCER]: new TrainerConfig(++t).setMoneyMultiplier(1.55).setEncounterBgm(TrainerType.CYCLIST) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_SAME_TWO_WEAK_SAME) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.RALTS, Species.SPOINK, Species.LOTAD, Species.BUDEW], - [TrainerPoolTier.UNCOMMON]: [Species.SPINDA, Species.SWABLU, Species.MARACTUS,], - [TrainerPoolTier.RARE]: [Species.BELLOSSOM, Species.HITMONTOP, Species.MIME_JR, Species.ORICORIO], - [TrainerPoolTier.SUPER_RARE]: [Species.POPPLIO] + [TrainerPoolTier.COMMON]: [ Species.RALTS, Species.SPOINK, Species.LOTAD, Species.BUDEW ], + [TrainerPoolTier.UNCOMMON]: [ Species.SPINDA, Species.SWABLU, Species.MARACTUS, ], + [TrainerPoolTier.RARE]: [ Species.BELLOSSOM, Species.HITMONTOP, Species.MIME_JR, Species.ORICORIO ], + [TrainerPoolTier.SUPER_RARE]: [ Species.POPPLIO ] }), [TrainerType.DEPOT_AGENT]: new TrainerConfig(++t).setMoneyMultiplier(1.45).setEncounterBgm(TrainerType.CLERK), [TrainerType.DOCTOR]: new TrainerConfig(++t).setHasGenders("Nurse", "lass").setHasDouble("Medical Team").setMoneyMultiplier(3).setEncounterBgm(TrainerType.CLERK) @@ -1387,20 +1387,20 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.FISHERMAN]: new TrainerConfig(++t).setMoneyMultiplier(1.25).setEncounterBgm(TrainerType.BACKPACKER).setSpecialtyTypes(Type.WATER) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.THREE_WEAK_SAME, trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.SIX_WEAKER) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.TENTACOOL, Species.MAGIKARP, Species.GOLDEEN, Species.STARYU, Species.REMORAID, Species.SKRELP, Species.CLAUNCHER, Species.ARROKUDA], - [TrainerPoolTier.UNCOMMON]: [Species.POLIWAG, Species.SHELLDER, Species.KRABBY, Species.HORSEA, Species.CARVANHA, Species.BARBOACH, Species.CORPHISH, Species.FINNEON, Species.TYMPOLE, Species.BASCULIN, Species.FRILLISH, Species.INKAY], - [TrainerPoolTier.RARE]: [Species.CHINCHOU, Species.CORSOLA, Species.WAILMER, Species.BARBOACH, Species.CLAMPERL, Species.LUVDISC, Species.MANTYKE, Species.ALOMOMOLA, Species.TATSUGIRI, Species.VELUZA], - [TrainerPoolTier.SUPER_RARE]: [Species.LAPRAS, Species.FEEBAS, Species.RELICANTH, Species.DONDOZO] + [TrainerPoolTier.COMMON]: [ Species.TENTACOOL, Species.MAGIKARP, Species.GOLDEEN, Species.STARYU, Species.REMORAID, Species.SKRELP, Species.CLAUNCHER, Species.ARROKUDA ], + [TrainerPoolTier.UNCOMMON]: [ Species.POLIWAG, Species.SHELLDER, Species.KRABBY, Species.HORSEA, Species.CARVANHA, Species.BARBOACH, Species.CORPHISH, Species.FINNEON, Species.TYMPOLE, Species.BASCULIN, Species.FRILLISH, Species.INKAY ], + [TrainerPoolTier.RARE]: [ Species.CHINCHOU, Species.CORSOLA, Species.WAILMER, Species.BARBOACH, Species.CLAMPERL, Species.LUVDISC, Species.MANTYKE, Species.ALOMOMOLA, Species.TATSUGIRI, Species.VELUZA ], + [TrainerPoolTier.SUPER_RARE]: [ Species.LAPRAS, Species.FEEBAS, Species.RELICANTH, Species.DONDOZO ] }), [TrainerType.GUITARIST]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.ROUGHNECK).setSpecialtyTypes(Type.ELECTRIC).setSpeciesFilter(s => s.isOfType(Type.ELECTRIC)), [TrainerType.HARLEQUIN]: new TrainerConfig(++t).setEncounterBgm(TrainerType.PSYCHIC).setSpeciesFilter(s => tmSpecies[Moves.TRICK_ROOM].indexOf(s.speciesId) > -1), [TrainerType.HIKER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.BACKPACKER) .setPartyTemplates(trainerPartyTemplates.TWO_AVG_SAME_ONE_AVG, trainerPartyTemplates.TWO_AVG_SAME_ONE_STRONG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.FOUR_WEAK, trainerPartyTemplates.ONE_STRONG) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.SANDSHREW, Species.DIGLETT, Species.GEODUDE, Species.MACHOP, Species.ARON, Species.ROGGENROLA, Species.DRILBUR, Species.NACLI], - [TrainerPoolTier.UNCOMMON]: [Species.ZUBAT, Species.RHYHORN, Species.ONIX, Species.CUBONE, Species.WOOBAT, Species.SWINUB, Species.NOSEPASS, Species.HIPPOPOTAS, Species.DWEBBLE, Species.KLAWF, Species.TOEDSCOOL], - [TrainerPoolTier.RARE]: [Species.TORKOAL, Species.TRAPINCH, Species.BARBOACH, Species.GOLETT, Species.ALOLA_DIGLETT, Species.ALOLA_GEODUDE, Species.GALAR_STUNFISK, Species.PALDEA_WOOPER], - [TrainerPoolTier.SUPER_RARE]: [Species.MAGBY, Species.LARVITAR] + [TrainerPoolTier.COMMON]: [ Species.SANDSHREW, Species.DIGLETT, Species.GEODUDE, Species.MACHOP, Species.ARON, Species.ROGGENROLA, Species.DRILBUR, Species.NACLI ], + [TrainerPoolTier.UNCOMMON]: [ Species.ZUBAT, Species.RHYHORN, Species.ONIX, Species.CUBONE, Species.WOOBAT, Species.SWINUB, Species.NOSEPASS, Species.HIPPOPOTAS, Species.DWEBBLE, Species.KLAWF, Species.TOEDSCOOL ], + [TrainerPoolTier.RARE]: [ Species.TORKOAL, Species.TRAPINCH, Species.BARBOACH, Species.GOLETT, Species.ALOLA_DIGLETT, Species.ALOLA_GEODUDE, Species.GALAR_STUNFISK, Species.PALDEA_WOOPER ], + [TrainerPoolTier.SUPER_RARE]: [ Species.MAGBY, Species.LARVITAR ] }), [TrainerType.HOOLIGANS]: new TrainerConfig(++t).setDoubleOnly().setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.POISON) || s.isOfType(Type.DARK)), [TrainerType.HOOPSTER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), @@ -1416,11 +1416,11 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.OFFICER]: new TrainerConfig(++t).setMoneyMultiplier(1.55).setEncounterBgm(TrainerType.CLERK) .setPartyTemplates(trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.VULPIX, Species.GROWLITHE, Species.SNUBBULL, Species.POOCHYENA, Species.ELECTRIKE, Species.LILLIPUP, Species.YAMPER, Species.FIDOUGH], - [TrainerPoolTier.UNCOMMON]: [Species.HOUNDOUR, Species.ROCKRUFF, Species.MASCHIFF], - [TrainerPoolTier.RARE]: [Species.JOLTEON, Species.RIOLU], + [TrainerPoolTier.COMMON]: [ Species.VULPIX, Species.GROWLITHE, Species.SNUBBULL, Species.POOCHYENA, Species.ELECTRIKE, Species.LILLIPUP, Species.YAMPER, Species.FIDOUGH ], + [TrainerPoolTier.UNCOMMON]: [ Species.HOUNDOUR, Species.ROCKRUFF, Species.MASCHIFF ], + [TrainerPoolTier.RARE]: [ Species.JOLTEON, Species.RIOLU ], [TrainerPoolTier.SUPER_RARE]: [], - [TrainerPoolTier.ULTRA_RARE]: [Species.ENTEI, Species.SUICUNE, Species.RAIKOU] + [TrainerPoolTier.ULTRA_RARE]: [ Species.ENTEI, Species.SUICUNE, Species.RAIKOU ] }), [TrainerType.PARASOL_LADY]: new TrainerConfig(++t).setMoneyMultiplier(1.55).setEncounterBgm(TrainerType.PARASOL_LADY).setSpeciesFilter(s => s.isOfType(Type.WATER)), [TrainerType.PILOT]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => tmSpecies[Moves.FLY].indexOf(s.speciesId) > -1), @@ -1429,25 +1429,25 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.PRESCHOOLER]: new TrainerConfig(++t).setMoneyMultiplier(0.2).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders("Preschooler Female", "lass").setHasDouble("Preschoolers") .setPartyTemplates(trainerPartyTemplates.THREE_WEAK, trainerPartyTemplates.FOUR_WEAKER, trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, trainerPartyTemplates.FIVE_WEAKER) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.CATERPIE, Species.PICHU, Species.SANDSHREW, Species.LEDYBA, Species.BUDEW, Species.BURMY, Species.WOOLOO, Species.PAWMI, Species.SMOLIV], - [TrainerPoolTier.UNCOMMON]: [Species.EEVEE, Species.CLEFFA, Species.IGGLYBUFF, Species.SWINUB, Species.WOOPER, Species.DRIFLOON, Species.DEDENNE, Species.STUFFUL], - [TrainerPoolTier.RARE]: [Species.RALTS, Species.RIOLU, Species.JOLTIK, Species.TANDEMAUS], - [TrainerPoolTier.SUPER_RARE]: [Species.DARUMAKA, Species.TINKATINK], + [TrainerPoolTier.COMMON]: [ Species.CATERPIE, Species.PICHU, Species.SANDSHREW, Species.LEDYBA, Species.BUDEW, Species.BURMY, Species.WOOLOO, Species.PAWMI, Species.SMOLIV ], + [TrainerPoolTier.UNCOMMON]: [ Species.EEVEE, Species.CLEFFA, Species.IGGLYBUFF, Species.SWINUB, Species.WOOPER, Species.DRIFLOON, Species.DEDENNE, Species.STUFFUL ], + [TrainerPoolTier.RARE]: [ Species.RALTS, Species.RIOLU, Species.JOLTIK, Species.TANDEMAUS ], + [TrainerPoolTier.SUPER_RARE]: [ Species.DARUMAKA, Species.TINKATINK ], }), [TrainerType.PSYCHIC]: new TrainerConfig(++t).setHasGenders("Psychic Female").setHasDouble("Psychics").setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.PSYCHIC) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, trainerPartyTemplates.TWO_WEAK_SAME_TWO_WEAK_SAME, trainerPartyTemplates.ONE_STRONGER) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.ABRA, Species.DROWZEE, Species.RALTS, Species.SPOINK, Species.GOTHITA, Species.SOLOSIS, Species.BLIPBUG, Species.ESPURR, Species.HATENNA], - [TrainerPoolTier.UNCOMMON]: [Species.MIME_JR, Species.EXEGGCUTE, Species.MEDITITE, Species.NATU, Species.EXEGGCUTE, Species.WOOBAT, Species.INKAY, Species.ORANGURU], - [TrainerPoolTier.RARE]: [Species.ELGYEM, Species.SIGILYPH, Species.BALTOY, Species.GIRAFARIG, Species.MEOWSTIC], - [TrainerPoolTier.SUPER_RARE]: [Species.BELDUM, Species.ESPEON, Species.STANTLER], + [TrainerPoolTier.COMMON]: [ Species.ABRA, Species.DROWZEE, Species.RALTS, Species.SPOINK, Species.GOTHITA, Species.SOLOSIS, Species.BLIPBUG, Species.ESPURR, Species.HATENNA ], + [TrainerPoolTier.UNCOMMON]: [ Species.MIME_JR, Species.EXEGGCUTE, Species.MEDITITE, Species.NATU, Species.EXEGGCUTE, Species.WOOBAT, Species.INKAY, Species.ORANGURU ], + [TrainerPoolTier.RARE]: [ Species.ELGYEM, Species.SIGILYPH, Species.BALTOY, Species.GIRAFARIG, Species.MEOWSTIC ], + [TrainerPoolTier.SUPER_RARE]: [ Species.BELDUM, Species.ESPEON, Species.STANTLER ], }), [TrainerType.RANGER]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setName("Pokémon Ranger").setEncounterBgm(TrainerType.BACKPACKER).setHasGenders("Pokémon Ranger Female").setHasDouble("Pokémon Rangers") .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.PICHU, Species.GROWLITHE, Species.PONYTA, Species.ZIGZAGOON, Species.SEEDOT, Species.BIDOOF, Species.RIOLU, Species.SEWADDLE, Species.SKIDDO, Species.SALANDIT, Species.YAMPER], - [TrainerPoolTier.UNCOMMON]: [Species.AZURILL, Species.TAUROS, Species.MAREEP, Species.FARFETCHD, Species.TEDDIURSA, Species.SHROOMISH, Species.ELECTRIKE, Species.BUDEW, Species.BUIZEL, Species.MUDBRAY, Species.STUFFUL], - [TrainerPoolTier.RARE]: [Species.EEVEE, Species.SCYTHER, Species.KANGASKHAN, Species.RALTS, Species.MUNCHLAX, Species.ZORUA, Species.PALDEA_TAUROS, Species.TINKATINK, Species.CYCLIZAR, Species.FLAMIGO], - [TrainerPoolTier.SUPER_RARE]: [Species.LARVESTA], + [TrainerPoolTier.COMMON]: [ Species.PICHU, Species.GROWLITHE, Species.PONYTA, Species.ZIGZAGOON, Species.SEEDOT, Species.BIDOOF, Species.RIOLU, Species.SEWADDLE, Species.SKIDDO, Species.SALANDIT, Species.YAMPER ], + [TrainerPoolTier.UNCOMMON]: [ Species.AZURILL, Species.TAUROS, Species.MAREEP, Species.FARFETCHD, Species.TEDDIURSA, Species.SHROOMISH, Species.ELECTRIKE, Species.BUDEW, Species.BUIZEL, Species.MUDBRAY, Species.STUFFUL ], + [TrainerPoolTier.RARE]: [ Species.EEVEE, Species.SCYTHER, Species.KANGASKHAN, Species.RALTS, Species.MUNCHLAX, Species.ZORUA, Species.PALDEA_TAUROS, Species.TINKATINK, Species.CYCLIZAR, Species.FLAMIGO ], + [TrainerPoolTier.SUPER_RARE]: [ Species.LARVESTA ], }), [TrainerType.RICH]: new TrainerConfig(++t).setMoneyMultiplier(5).setName("Gentleman").setHasGenders("Madame").setHasDouble("Rich Couple"), [TrainerType.RICH_KID]: new TrainerConfig(++t).setMoneyMultiplier(3.75).setName("Rich Boy").setHasGenders("Lady").setHasDouble("Rich Kids").setEncounterBgm(TrainerType.RICH), @@ -1455,150 +1455,150 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.SAILOR]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.BACKPACKER).setSpeciesFilter(s => s.isOfType(Type.WATER) || s.isOfType(Type.FIGHTING)), [TrainerType.SCIENTIST]: new TrainerConfig(++t).setHasGenders("Scientist Female").setHasDouble("Scientists").setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.SCIENTIST) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.MAGNEMITE, Species.GRIMER, Species.DROWZEE, Species.VOLTORB, Species.KOFFING], - [TrainerPoolTier.UNCOMMON]: [Species.BALTOY, Species.BRONZOR, Species.FERROSEED, Species.KLINK, Species.CHARJABUG, Species.BLIPBUG, Species.HELIOPTILE], - [TrainerPoolTier.RARE]: [Species.ABRA, Species.DITTO, Species.PORYGON, Species.ELEKID, Species.SOLOSIS, Species.GALAR_WEEZING], - [TrainerPoolTier.SUPER_RARE]: [Species.OMANYTE, Species.KABUTO, Species.AERODACTYL, Species.LILEEP, Species.ANORITH, Species.CRANIDOS, Species.SHIELDON, Species.TIRTOUGA, Species.ARCHEN, Species.ARCTOVISH, Species.ARCTOZOLT, Species.DRACOVISH, Species.DRACOZOLT], - [TrainerPoolTier.ULTRA_RARE]: [Species.ROTOM, Species.MELTAN] + [TrainerPoolTier.COMMON]: [ Species.MAGNEMITE, Species.GRIMER, Species.DROWZEE, Species.VOLTORB, Species.KOFFING ], + [TrainerPoolTier.UNCOMMON]: [ Species.BALTOY, Species.BRONZOR, Species.FERROSEED, Species.KLINK, Species.CHARJABUG, Species.BLIPBUG, Species.HELIOPTILE ], + [TrainerPoolTier.RARE]: [ Species.ABRA, Species.DITTO, Species.PORYGON, Species.ELEKID, Species.SOLOSIS, Species.GALAR_WEEZING ], + [TrainerPoolTier.SUPER_RARE]: [ Species.OMANYTE, Species.KABUTO, Species.AERODACTYL, Species.LILEEP, Species.ANORITH, Species.CRANIDOS, Species.SHIELDON, Species.TIRTOUGA, Species.ARCHEN, Species.ARCTOVISH, Species.ARCTOZOLT, Species.DRACOVISH, Species.DRACOZOLT ], + [TrainerPoolTier.ULTRA_RARE]: [ Species.ROTOM, Species.MELTAN ] }), [TrainerType.SMASHER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), [TrainerType.SNOW_WORKER]: new TrainerConfig(++t).setName("Worker").setHasDouble("Workers").setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => s.isOfType(Type.ICE) || s.isOfType(Type.STEEL)), [TrainerType.STRIKER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), [TrainerType.SCHOOL_KID]: new TrainerConfig(++t).setMoneyMultiplier(0.75).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders("School Kid Female", "lass").setHasDouble("School Kids") .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.ODDISH, Species.EXEGGCUTE, Species.TEDDIURSA, Species.WURMPLE, Species.RALTS, Species.SHROOMISH, Species.FLETCHLING], - [TrainerPoolTier.UNCOMMON]: [Species.VOLTORB, Species.WHISMUR, Species.MEDITITE, Species.MIME_JR, Species.NYMBLE], - [TrainerPoolTier.RARE]: [Species.TANGELA, Species.EEVEE, Species.YANMA], - [TrainerPoolTier.SUPER_RARE]: [Species.TADBULB] + [TrainerPoolTier.COMMON]: [ Species.ODDISH, Species.EXEGGCUTE, Species.TEDDIURSA, Species.WURMPLE, Species.RALTS, Species.SHROOMISH, Species.FLETCHLING ], + [TrainerPoolTier.UNCOMMON]: [ Species.VOLTORB, Species.WHISMUR, Species.MEDITITE, Species.MIME_JR, Species.NYMBLE ], + [TrainerPoolTier.RARE]: [ Species.TANGELA, Species.EEVEE, Species.YANMA ], + [TrainerPoolTier.SUPER_RARE]: [ Species.TADBULB ] }), [TrainerType.SWIMMER]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setEncounterBgm(TrainerType.PARASOL_LADY).setHasGenders("Swimmer Female").setHasDouble("Swimmers").setSpecialtyTypes(Type.WATER).setSpeciesFilter(s => s.isOfType(Type.WATER)), [TrainerType.TWINS]: new TrainerConfig(++t).setDoubleOnly().setMoneyMultiplier(0.65).setUseSameSeedForAllMembers() .setPartyTemplateFunc(scene => getWavePartyTemplate(scene, trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_STRONG)) - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PLUSLE, Species.VOLBEAT, Species.PACHIRISU, Species.SILCOON, Species.METAPOD, Species.IGGLYBUFF, Species.PETILIL, Species.EEVEE])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.MINUN, Species.ILLUMISE, Species.EMOLGA, Species.CASCOON, Species.KAKUNA, Species.CLEFFA, Species.COTTONEE, Species.EEVEE], TrainerSlot.TRAINER_PARTNER)) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PLUSLE, Species.VOLBEAT, Species.PACHIRISU, Species.SILCOON, Species.METAPOD, Species.IGGLYBUFF, Species.PETILIL, Species.EEVEE ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MINUN, Species.ILLUMISE, Species.EMOLGA, Species.CASCOON, Species.KAKUNA, Species.CLEFFA, Species.COTTONEE, Species.EEVEE ], TrainerSlot.TRAINER_PARTNER)) .setEncounterBgm(TrainerType.TWINS), [TrainerType.VETERAN]: new TrainerConfig(++t).setHasGenders("Veteran Female").setHasDouble("Veteran Duo").setMoneyMultiplier(2.5).setEncounterBgm(TrainerType.ACE_TRAINER).setSpeciesFilter(s => s.isOfType(Type.DRAGON)), [TrainerType.WAITER]: new TrainerConfig(++t).setHasGenders("Waitress").setHasDouble("Restaurant Staff").setMoneyMultiplier(1.5).setEncounterBgm(TrainerType.CLERK) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.CLEFFA, Species.CHATOT, Species.PANSAGE, Species.PANSEAR, Species.PANPOUR, Species.MINCCINO], - [TrainerPoolTier.UNCOMMON]: [Species.TROPIUS, Species.PETILIL, Species.BOUNSWEET, Species.INDEEDEE], - [TrainerPoolTier.RARE]: [Species.APPLIN, Species.SINISTEA, Species.POLTCHAGEIST] + [TrainerPoolTier.COMMON]: [ Species.CLEFFA, Species.CHATOT, Species.PANSAGE, Species.PANSEAR, Species.PANPOUR, Species.MINCCINO ], + [TrainerPoolTier.UNCOMMON]: [ Species.TROPIUS, Species.PETILIL, Species.BOUNSWEET, Species.INDEEDEE ], + [TrainerPoolTier.RARE]: [ Species.APPLIN, Species.SINISTEA, Species.POLTCHAGEIST ] }), [TrainerType.WORKER]: new TrainerConfig(++t).setHasGenders("Worker Female").setHasDouble("Workers").setEncounterBgm(TrainerType.CLERK).setMoneyMultiplier(1.7).setSpeciesFilter(s => s.isOfType(Type.ROCK) || s.isOfType(Type.STEEL)), [TrainerType.YOUNGSTER]: new TrainerConfig(++t).setMoneyMultiplier(0.5).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders("Lass", "lass").setHasDouble("Beginners").setPartyTemplates(trainerPartyTemplates.TWO_WEAKER) .setSpeciesPools( - [Species.CATERPIE, Species.WEEDLE, Species.RATTATA, Species.SENTRET, Species.POOCHYENA, Species.ZIGZAGOON, Species.WURMPLE, Species.BIDOOF, Species.PATRAT, Species.LILLIPUP] + [ Species.CATERPIE, Species.WEEDLE, Species.RATTATA, Species.SENTRET, Species.POOCHYENA, Species.ZIGZAGOON, Species.WURMPLE, Species.BIDOOF, Species.PATRAT, Species.LILLIPUP ] ), [TrainerType.ROCKET_GRUNT]: new TrainerConfig(++t).setHasGenders("Rocket Grunt Female").setHasDouble("Rocket Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.WEEDLE, Species.RATTATA, Species.EKANS, Species.SANDSHREW, Species.ZUBAT, Species.GEODUDE, Species.KOFFING, Species.GRIMER, Species.ODDISH, Species.SLOWPOKE], - [TrainerPoolTier.UNCOMMON]: [Species.GYARADOS, Species.LICKITUNG, Species.TAUROS, Species.MANKEY, Species.SCYTHER, Species.ELEKID, Species.MAGBY, Species.CUBONE, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB, Species.MAGNEMITE], - [TrainerPoolTier.RARE]: [Species.PORYGON, Species.ALOLA_RATTATA, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE, Species.PALDEA_TAUROS, Species.OMANYTE, Species.KABUTO], - [TrainerPoolTier.SUPER_RARE]: [Species.DRATINI, Species.LARVITAR] + [TrainerPoolTier.COMMON]: [ Species.WEEDLE, Species.RATTATA, Species.EKANS, Species.SANDSHREW, Species.ZUBAT, Species.GEODUDE, Species.KOFFING, Species.GRIMER, Species.ODDISH, Species.SLOWPOKE ], + [TrainerPoolTier.UNCOMMON]: [ Species.GYARADOS, Species.LICKITUNG, Species.TAUROS, Species.MANKEY, Species.SCYTHER, Species.ELEKID, Species.MAGBY, Species.CUBONE, Species.GROWLITHE, Species.MURKROW, Species.GASTLY, Species.EXEGGCUTE, Species.VOLTORB, Species.MAGNEMITE ], + [TrainerPoolTier.RARE]: [ Species.PORYGON, Species.ALOLA_RATTATA, Species.ALOLA_SANDSHREW, Species.ALOLA_MEOWTH, Species.ALOLA_GRIMER, Species.ALOLA_GEODUDE, Species.PALDEA_TAUROS, Species.OMANYTE, Species.KABUTO ], + [TrainerPoolTier.SUPER_RARE]: [ Species.DRATINI, Species.LARVITAR ] }), - [TrainerType.ARCHER]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("rocket_admin", "rocket", [Species.HOUNDOOM]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), - [TrainerType.ARIANA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("rocket_admin_female", "rocket", [Species.ARBOK]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), - [TrainerType.PROTON]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("rocket_admin", "rocket", [Species.CROBAT]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), - [TrainerType.PETREL]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("rocket_admin", "rocket", [Species.WEEZING]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.ARCHER]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("rocket_admin", "rocket", [ Species.HOUNDOOM ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.ARIANA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("rocket_admin_female", "rocket", [ Species.ARBOK ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.PROTON]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("rocket_admin", "rocket", [ Species.CROBAT ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.PETREL]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("rocket_admin", "rocket", [ Species.WEEZING ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_rocket_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), [TrainerType.MAGMA_GRUNT]: new TrainerConfig(++t).setHasGenders("Magma Grunt Female").setHasDouble("Magma Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.SLUGMA, Species.POOCHYENA, Species.NUMEL, Species.ZIGZAGOON, Species.DIGLETT, Species.MAGBY, Species.TORKOAL, Species.GROWLITHE, Species.BALTOY], - [TrainerPoolTier.UNCOMMON]: [Species.SOLROCK, Species.HIPPOPOTAS, Species.SANDACONDA, Species.PHANPY, Species.ROLYCOLY, Species.GLIGAR, Species.RHYHORN, Species.HEATMOR], - [TrainerPoolTier.RARE]: [Species.TRAPINCH, Species.LILEEP, Species.ANORITH, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON], - [TrainerPoolTier.SUPER_RARE]: [Species.CAPSAKID, Species.CHARCADET] + [TrainerPoolTier.COMMON]: [ Species.SLUGMA, Species.POOCHYENA, Species.NUMEL, Species.ZIGZAGOON, Species.DIGLETT, Species.MAGBY, Species.TORKOAL, Species.GROWLITHE, Species.BALTOY ], + [TrainerPoolTier.UNCOMMON]: [ Species.SOLROCK, Species.HIPPOPOTAS, Species.SANDACONDA, Species.PHANPY, Species.ROLYCOLY, Species.GLIGAR, Species.RHYHORN, Species.HEATMOR ], + [TrainerPoolTier.RARE]: [ Species.TRAPINCH, Species.LILEEP, Species.ANORITH, Species.HISUI_GROWLITHE, Species.TURTONATOR, Species.ARON, Species.TOEDSCOOL ], + [TrainerPoolTier.SUPER_RARE]: [ Species.CAPSAKID, Species.CHARCADET ] }), - [TrainerType.TABITHA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("magma_admin", "magma", [Species.CAMERUPT]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), - [TrainerType.COURTNEY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("magma_admin_female", "magma", [Species.CAMERUPT]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.TABITHA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("magma_admin", "magma", [ Species.CAMERUPT ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.COURTNEY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("magma_admin_female", "magma", [ Species.CAMERUPT ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), [TrainerType.AQUA_GRUNT]: new TrainerConfig(++t).setHasGenders("Aqua Grunt Female").setHasDouble("Aqua Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.CARVANHA, Species.WAILMER, Species.ZIGZAGOON, Species.LOTAD, Species.CORPHISH, Species.SPHEAL, Species.REMORAID, Species.QWILFISH, Species.BARBOACH], - [TrainerPoolTier.UNCOMMON]: [Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.AZURILL, Species.CLOBBOPUS, Species.HORSEA], - [TrainerPoolTier.RARE]: [Species.MANTYKE, Species.DHELMISE, Species.HISUI_QWILFISH, Species.ARROKUDA, Species.PALDEA_WOOPER, Species.SKRELP], - [TrainerPoolTier.SUPER_RARE]: [Species.DONDOZO, Species.BASCULEGION] + [TrainerPoolTier.COMMON]: [ Species.CARVANHA, Species.WAILMER, Species.ZIGZAGOON, Species.LOTAD, Species.CORPHISH, Species.SPHEAL, Species.REMORAID, Species.QWILFISH, Species.BARBOACH ], + [TrainerPoolTier.UNCOMMON]: [ Species.CLAMPERL, Species.CHINCHOU, Species.WOOPER, Species.WINGULL, Species.TENTACOOL, Species.AZURILL, Species.CLOBBOPUS, Species.HORSEA ], + [TrainerPoolTier.RARE]: [ Species.MANTYKE, Species.DHELMISE, Species.HISUI_QWILFISH, Species.ARROKUDA, Species.PALDEA_WOOPER, Species.SKRELP ], + [TrainerPoolTier.SUPER_RARE]: [ Species.DONDOZO, Species.BASCULEGION ] }), - [TrainerType.MATT]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("aqua_admin", "aqua", [Species.SHARPEDO]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), - [TrainerType.SHELLY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("aqua_admin_female", "aqua", [Species.SHARPEDO]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.MATT]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("aqua_admin", "aqua", [ Species.SHARPEDO ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.SHELLY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("aqua_admin_female", "aqua", [ Species.SHARPEDO ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aqua_magma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), [TrainerType.GALACTIC_GRUNT]: new TrainerConfig(++t).setHasGenders("Galactic Grunt Female").setHasDouble("Galactic Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.GLAMEOW, Species.STUNKY, Species.CROAGUNK, Species.SHINX, Species.WURMPLE, Species.BRONZOR, Species.DRIFLOON, Species.BURMY, Species.CARNIVINE], - [TrainerPoolTier.UNCOMMON]: [Species.LICKITUNG, Species.RHYHORN, Species.TANGELA, Species.ZUBAT, Species.YANMA, Species.SKORUPI, Species.GLIGAR, Species.SWINUB], - [TrainerPoolTier.RARE]: [Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.SNEASEL, Species.ELEKID, Species.MAGBY, Species.DUSKULL], - [TrainerPoolTier.SUPER_RARE]: [Species.ROTOM, Species.SPIRITOMB, Species.HISUI_SNEASEL] + [TrainerPoolTier.COMMON]: [ Species.GLAMEOW, Species.STUNKY, Species.CROAGUNK, Species.SHINX, Species.WURMPLE, Species.BRONZOR, Species.DRIFLOON, Species.BURMY, Species.CARNIVINE ], + [TrainerPoolTier.UNCOMMON]: [ Species.LICKITUNG, Species.RHYHORN, Species.TANGELA, Species.ZUBAT, Species.YANMA, Species.SKORUPI, Species.GLIGAR, Species.SWINUB ], + [TrainerPoolTier.RARE]: [ Species.HISUI_GROWLITHE, Species.HISUI_QWILFISH, Species.SNEASEL, Species.ELEKID, Species.MAGBY, Species.DUSKULL ], + [TrainerPoolTier.SUPER_RARE]: [ Species.ROTOM, Species.SPIRITOMB, Species.HISUI_SNEASEL ] }), - [TrainerType.JUPITER]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("galactic_commander_female", "galactic", [Species.SKUNTANK]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), - [TrainerType.MARS]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("galactic_commander_female", "galactic", [Species.PURUGLY]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), - [TrainerType.SATURN]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("galactic_commander", "galactic", [Species.TOXICROAK]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.JUPITER]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("galactic_commander_female", "galactic", [ Species.SKUNTANK ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.MARS]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("galactic_commander_female", "galactic", [ Species.PURUGLY ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.SATURN]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("galactic_commander", "galactic", [ Species.TOXICROAK ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_galactic_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), [TrainerType.PLASMA_GRUNT]: new TrainerConfig(++t).setHasGenders("Plasma Grunt Female").setHasDouble("Plasma Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_plasma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.PATRAT, Species.LILLIPUP, Species.PURRLOIN, Species.SCRAFTY, Species.WOOBAT, Species.VANILLITE, Species.SANDILE, Species.TRUBBISH, Species.TYMPOLE], - [TrainerPoolTier.UNCOMMON]: [Species.FRILLISH, Species.VENIPEDE, Species.GOLETT, Species.TIMBURR, Species.DARUMAKA, Species.FOONGUS, Species.JOLTIK, Species.CUBCHOO, Species.KLINK], - [TrainerPoolTier.RARE]: [Species.PAWNIARD, Species.RUFFLET, Species.VULLABY, Species.ZORUA, Species.DRILBUR, Species.MIENFOO, Species.DURANT, Species.BOUFFALANT], - [TrainerPoolTier.SUPER_RARE]: [Species.DRUDDIGON, Species.HISUI_ZORUA, Species.AXEW, Species.DEINO] + [TrainerPoolTier.COMMON]: [ Species.PATRAT, Species.LILLIPUP, Species.PURRLOIN, Species.SCRAFTY, Species.WOOBAT, Species.VANILLITE, Species.SANDILE, Species.TRUBBISH, Species.TYMPOLE ], + [TrainerPoolTier.UNCOMMON]: [ Species.FRILLISH, Species.VENIPEDE, Species.GOLETT, Species.TIMBURR, Species.DARUMAKA, Species.FOONGUS, Species.JOLTIK, Species.CUBCHOO, Species.KLINK ], + [TrainerPoolTier.RARE]: [ Species.PAWNIARD, Species.RUFFLET, Species.VULLABY, Species.ZORUA, Species.DRILBUR, Species.MIENFOO, Species.DURANT, Species.BOUFFALANT ], + [TrainerPoolTier.SUPER_RARE]: [ Species.DRUDDIGON, Species.HISUI_ZORUA, Species.AXEW, Species.DEINO ] }), - [TrainerType.ZINZOLIN]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("plasma_sage", "plasma", [Species.CRYOGONAL]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_plasma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), - [TrainerType.ROOD]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("plasma_sage", "plasma", [Species.SWOOBAT]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_plasma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.ZINZOLIN]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("plasma_sage", "plasma", [ Species.CRYOGONAL ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_plasma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.ROOD]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("plasma_sage", "plasma", [ Species.SWOOBAT ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_plasma_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), [TrainerType.FLARE_GRUNT]: new TrainerConfig(++t).setHasGenders("Flare Grunt Female").setHasDouble("Flare Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [Species.FLETCHLING, Species.LITLEO, Species.PONYTA, Species.INKAY, Species.HOUNDOUR, Species.SKORUPI, Species.SCRAFTY, Species.CROAGUNK, Species.SCATTERBUG, Species.ESPURR], - [TrainerPoolTier.UNCOMMON]: [Species.HELIOPTILE, Species.ELECTRIKE, Species.SKRELP, Species.PANCHAM, Species.PURRLOIN, Species.POOCHYENA, Species.BINACLE, Species.CLAUNCHER, Species.PUMPKABOO, Species.PHANTUMP], - [TrainerPoolTier.RARE]: [Species.LITWICK, Species.SNEASEL, Species.PAWNIARD, Species.SLIGGOO], - [TrainerPoolTier.SUPER_RARE]: [Species.NOIVERN, Species.HISUI_SLIGGOO, Species.HISUI_AVALUGG] + [TrainerPoolTier.COMMON]: [ Species.FLETCHLING, Species.LITLEO, Species.PONYTA, Species.INKAY, Species.HOUNDOUR, Species.SKORUPI, Species.SCRAFTY, Species.CROAGUNK, Species.SCATTERBUG, Species.ESPURR ], + [TrainerPoolTier.UNCOMMON]: [ Species.HELIOPTILE, Species.ELECTRIKE, Species.SKRELP, Species.PANCHAM, Species.PURRLOIN, Species.POOCHYENA, Species.BINACLE, Species.CLAUNCHER, Species.PUMPKABOO, Species.PHANTUMP, Species.FOONGUS ], + [TrainerPoolTier.RARE]: [ Species.LITWICK, Species.SNEASEL, Species.PAWNIARD, Species.SLIGGOO ], + [TrainerPoolTier.SUPER_RARE]: [ Species.NOIBAT, Species.HISUI_SLIGGOO, Species.HISUI_AVALUGG ] }), - [TrainerType.BRYONY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("flare_admin_female", "flare", [Species.LIEPARD]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), - [TrainerType.XEROSIC]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("flare_admin", "flare", [Species.MALAMAR]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.BRYONY]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("flare_admin_female", "flare", [ Species.LIEPARD ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.XEROSIC]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("flare_admin", "flare", [ Species.MALAMAR ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_flare_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), [TrainerType.AETHER_GRUNT]: new TrainerConfig(++t).setHasGenders("Aether Grunt Female").setHasDouble("Aether Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aether_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [ Species.PIKIPEK, Species.ROCKRUFF, Species.ALOLA_DIGLETT, Species.ALOLA_EXEGGUTOR, Species.YUNGOOS, Species.CORSOLA, Species.ALOLA_GEODUDE, Species.ALOLA_RAICHU, Species.BOUNSWEET, Species.LILLIPUP, Species.KOMALA, Species.MORELULL, Species.COMFEY, Species.TOGEDEMARU], - [TrainerPoolTier.UNCOMMON]: [ Species.POLIWAG, Species.STUFFUL, Species.ORANGURU, Species.PASSIMIAN, Species.BRUXISH, Species.MINIOR, Species.WISHIWASHI, Species.ALOLA_SANDSHREW, Species.ALOLA_VULPIX, Species.CRABRAWLER, Species.CUTIEFLY, Species.ORICORIO, Species.MUDBRAY, Species.PYUKUMUKU, Species.ALOLA_MAROWAK], - [TrainerPoolTier.RARE]: [ Species.GALAR_CORSOLA, Species.TURTONATOR, Species.MIMIKYU, Species.MAGNEMITE, Species.DRAMPA], - [TrainerPoolTier.SUPER_RARE]: [Species.JANGMO_O, Species.PORYGON] + [TrainerPoolTier.COMMON]: [ Species.PIKIPEK, Species.ROCKRUFF, Species.ALOLA_DIGLETT, Species.ALOLA_EXEGGUTOR, Species.YUNGOOS, Species.CORSOLA, Species.ALOLA_GEODUDE, Species.ALOLA_RAICHU, Species.BOUNSWEET, Species.LILLIPUP, Species.KOMALA, Species.MORELULL, Species.COMFEY, Species.TOGEDEMARU ], + [TrainerPoolTier.UNCOMMON]: [ Species.POLIWAG, Species.STUFFUL, Species.ORANGURU, Species.PASSIMIAN, Species.BRUXISH, Species.MINIOR, Species.WISHIWASHI, Species.ALOLA_SANDSHREW, Species.ALOLA_VULPIX, Species.CRABRAWLER, Species.CUTIEFLY, Species.ORICORIO, Species.MUDBRAY, Species.PYUKUMUKU, Species.ALOLA_MAROWAK ], + [TrainerPoolTier.RARE]: [ Species.GALAR_CORSOLA, Species.TURTONATOR, Species.MIMIKYU, Species.MAGNEMITE, Species.DRAMPA ], + [TrainerPoolTier.SUPER_RARE]: [ Species.JANGMO_O, Species.PORYGON ] }), - [TrainerType.FABA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("aether_admin", "aether", [Species.HYPNO]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aether_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.FABA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("aether_admin", "aether", [ Species.HYPNO ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_aether_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), [TrainerType.SKULL_GRUNT]: new TrainerConfig(++t).setHasGenders("Skull Grunt Female").setHasDouble("Skull Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_skull_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [ Species.SALANDIT, Species.ALOLA_RATTATA, Species.EKANS, Species.ALOLA_MEOWTH, Species.SCRAGGY, Species.KOFFING, Species.ALOLA_GRIMER, Species.MAREANIE, Species.SPINARAK, Species.TRUBBISH, Species.DROWZEE], - [TrainerPoolTier.UNCOMMON]: [ Species.FOMANTIS, Species.SABLEYE, Species.SANDILE, Species.HOUNDOUR, Species.ALOLA_MAROWAK, Species.GASTLY, Species.PANCHAM, Species.ZUBAT, Species.VENIPEDE, Species.VULLABY], - [TrainerPoolTier.RARE]: [Species.SANDYGAST, Species.PAWNIARD, Species.MIMIKYU, Species.DHELMISE, Species.WISHIWASHI, Species.NYMBLE], - [TrainerPoolTier.SUPER_RARE]: [Species.GRUBBIN, Species.DEWPIDER] + [TrainerPoolTier.COMMON]: [ Species.SALANDIT, Species.ALOLA_RATTATA, Species.EKANS, Species.ALOLA_MEOWTH, Species.SCRAGGY, Species.KOFFING, Species.ALOLA_GRIMER, Species.MAREANIE, Species.SPINARAK, Species.TRUBBISH, Species.DROWZEE ], + [TrainerPoolTier.UNCOMMON]: [ Species.FOMANTIS, Species.SABLEYE, Species.SANDILE, Species.HOUNDOUR, Species.ALOLA_MAROWAK, Species.GASTLY, Species.PANCHAM, Species.ZUBAT, Species.VENIPEDE, Species.VULLABY ], + [TrainerPoolTier.RARE]: [ Species.SANDYGAST, Species.PAWNIARD, Species.MIMIKYU, Species.DHELMISE, Species.WISHIWASHI, Species.NYMBLE ], + [TrainerPoolTier.SUPER_RARE]: [ Species.GRUBBIN, Species.DEWPIDER ] }), - [TrainerType.PLUMERIA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("skull_admin", "skull", [Species.SALAZZLE]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_skull_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.PLUMERIA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("skull_admin", "skull", [ Species.SALAZZLE ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_skull_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), [TrainerType.MACRO_GRUNT]: new TrainerConfig(++t).setHasGenders("Macro Grunt Female").setHasDouble("Macro Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_macro_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) .setSpeciesPools({ - [TrainerPoolTier.COMMON]: [ Species.CUFANT, Species.GALAR_MEOWTH, Species.KLINK, Species.ROOKIDEE, Species.CRAMORANT, Species.GALAR_ZIGZAGOON, Species.SKWOVET, Species.STEELIX, Species.MAWILE, Species.FERROSEED], - [TrainerPoolTier.UNCOMMON]: [ Species.DRILBUR, Species.MAGNEMITE, Species.HATENNA, Species.ARROKUDA, Species.APPLIN, Species.GALAR_PONYTA, Species.GALAR_YAMASK, Species.SINISTEA, Species.RIOLU], - [TrainerPoolTier.RARE]: [Species.FALINKS, Species.BELDUM, Species.GALAR_FARFETCHD, Species.GALAR_MR_MIME, Species.HONEDGE, Species.SCIZOR, Species.GALAR_DARUMAKA], - [TrainerPoolTier.SUPER_RARE]: [Species.DURALUDON, Species.DREEPY] + [TrainerPoolTier.COMMON]: [ Species.CUFANT, Species.GALAR_MEOWTH, Species.KLINK, Species.ROOKIDEE, Species.CRAMORANT, Species.GALAR_ZIGZAGOON, Species.SKWOVET, Species.STEELIX, Species.MAWILE, Species.FERROSEED ], + [TrainerPoolTier.UNCOMMON]: [ Species.DRILBUR, Species.MAGNEMITE, Species.HATENNA, Species.ARROKUDA, Species.APPLIN, Species.GALAR_PONYTA, Species.GALAR_YAMASK, Species.SINISTEA, Species.RIOLU ], + [TrainerPoolTier.RARE]: [ Species.FALINKS, Species.BELDUM, Species.GALAR_FARFETCHD, Species.GALAR_MR_MIME, Species.HONEDGE, Species.SCIZOR, Species.GALAR_DARUMAKA ], + [TrainerPoolTier.SUPER_RARE]: [ Species.DURALUDON, Species.DREEPY ] }), - [TrainerType.OLEANA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("macro_admin", "macro", [Species.GARBODOR]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_oleana").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), + [TrainerType.OLEANA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("macro_admin", "macro", [ Species.GARBODOR ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_oleana").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)), [TrainerType.STAR_GRUNT]: new TrainerConfig(++t).setHasGenders("Star Grunt Female").setHasDouble("Star Grunts").setMoneyMultiplier(1.0).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_grunt").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.DUNSPARCE, Species.HOUNDOUR, Species.AZURILL, Species.GULPIN, Species.FOONGUS, Species.FLETCHLING, Species.LITLEO, Species.FLABEBE, Species.CRABRAWLER, Species.NYMBLE, Species.PAWMI, Species.FIDOUGH, Species.SQUAWKABILLY, Species.MASCHIFF, Species.SHROODLE, Species.KLAWF, Species.WIGLETT, Species.PALDEA_WOOPER ], [TrainerPoolTier.UNCOMMON]: [ Species.KOFFING, Species.EEVEE, Species.GIRAFARIG, Species.RALTS, Species.TORKOAL, Species.SEVIPER, Species.SCRAGGY, Species.ZORUA, Species.MIMIKYU, Species.IMPIDIMP, Species.FALINKS, Species.CAPSAKID, Species.TINKATINK, Species.BOMBIRDIER, Species.CYCLIZAR, Species.FLAMIGO, Species.PALDEA_TAUROS ], - [TrainerPoolTier.RARE]: [ Species.MANKEY, Species.PAWNIARD, Species.CHARCADET, Species.FLITTLE, Species.VAROOM, Species.ORTHWORM], + [TrainerPoolTier.RARE]: [ Species.MANKEY, Species.PAWNIARD, Species.CHARCADET, Species.FLITTLE, Species.VAROOM, Species.ORTHWORM ], [TrainerPoolTier.SUPER_RARE]: [ Species.DONDOZO, Species.GIMMIGHOUL ] }), - [TrainerType.GIACOMO]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_1", [Species.KINGAMBIT]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.REVAVROOM], TrainerSlot.TRAINER, true, p => { + [TrainerType.GIACOMO]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_1", [ Species.KINGAMBIT ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Segin Starmobile p.moveset = [ new PokemonMove(Moves.WICKED_TORQUE), new PokemonMove(Moves.SPIN_OUT), new PokemonMove(Moves.SHIFT_GEAR), new PokemonMove(Moves.HIGH_HORSEPOWER) ]; })), - [TrainerType.MELA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_2", [Species.ARMAROUGE]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.REVAVROOM], TrainerSlot.TRAINER, true, p => { + [TrainerType.MELA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_2", [ Species.ARMAROUGE ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => { p.formIndex = 2; // Schedar Starmobile p.moveset = [ new PokemonMove(Moves.BLAZING_TORQUE), new PokemonMove(Moves.SPIN_OUT), new PokemonMove(Moves.SHIFT_GEAR), new PokemonMove(Moves.HIGH_HORSEPOWER) ]; })), - [TrainerType.ATTICUS]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_3", [Species.REVAVROOM]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.REVAVROOM], TrainerSlot.TRAINER, true, p => { + [TrainerType.ATTICUS]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_3", [ Species.REVAVROOM ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => { p.formIndex = 3; // Navi Starmobile p.moveset = [ new PokemonMove(Moves.NOXIOUS_TORQUE), new PokemonMove(Moves.SPIN_OUT), new PokemonMove(Moves.SHIFT_GEAR), new PokemonMove(Moves.HIGH_HORSEPOWER) ]; })), - [TrainerType.ORTEGA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_4", [Species.DACHSBUN]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.REVAVROOM], TrainerSlot.TRAINER, true, p => { + [TrainerType.ORTEGA]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_4", [ Species.DACHSBUN ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => { p.formIndex = 4; // Ruchbah Starmobile p.moveset = [ new PokemonMove(Moves.MAGICAL_TORQUE), new PokemonMove(Moves.SPIN_OUT), new PokemonMove(Moves.SHIFT_GEAR), new PokemonMove(Moves.HIGH_HORSEPOWER) ]; })), - [TrainerType.ERI]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_5", [Species.ANNIHILAPE]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.REVAVROOM], TrainerSlot.TRAINER, true, p => { + [TrainerType.ERI]: new TrainerConfig(++t).setMoneyMultiplier(1.5).initForEvilTeamAdmin("star_admin", "star_5", [ Species.ANNIHILAPE ]).setEncounterBgm(TrainerType.PLASMA_GRUNT).setBattleBgm("battle_plasma_grunt").setMixedBattleBgm("battle_star_admin").setVictoryBgm("victory_team_plasma").setPartyTemplateFunc(scene => getEvilGruntPartyTemplate(scene)) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => { p.formIndex = 5; // Caph Starmobile p.moveset = [ new PokemonMove(Moves.COMBAT_TORQUE), new PokemonMove(Moves.SPIN_OUT), new PokemonMove(Moves.SHIFT_GEAR), new PokemonMove(Moves.HIGH_HORSEPOWER) ]; })), @@ -1721,141 +1721,141 @@ export const trainerConfigs: TrainerConfigs = { [TrainerType.DRAYTON]: new TrainerConfig(++t).initForEliteFour(signatureSpecies["DRAYTON"], true, Type.DRAGON).setMixedBattleBgm("battle_bb_elite"), [TrainerType.BLUE]: new TrainerConfig((t = TrainerType.BLUE)).initForChampion(signatureSpecies["BLUE"], true).setBattleBgm("battle_kanto_champion").setMixedBattleBgm("battle_kanto_champion").setHasDouble("blue_red_double").setDoubleTrainerType(TrainerType.RED).setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALAKAZAM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ALAKAZAM ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Pidgeot p.generateAndPopulateMoveset(); p.generateName(); })), [TrainerType.RED]: new TrainerConfig(++t).initForChampion(signatureSpecies["RED"], true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion").setHasDouble("red_blue_double").setDoubleTrainerType(TrainerType.BLUE).setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PIKACHU], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PIKACHU ], TrainerSlot.TRAINER, true, p => { p.formIndex = 8; // G-Max Pikachu p.generateAndPopulateMoveset(); p.generateName(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Venusaur, Mega Charizard X, or Mega Blastoise p.generateAndPopulateMoveset(); p.generateName(); })), [TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t).setName("Lance").initForChampion(signatureSpecies["LANCE_CHAMPION"], true).setBattleBgm("battle_johto_champion").setMixedBattleBgm("battle_johto_champion") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.AERODACTYL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AERODACTYL ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.LATIAS, Species.LATIOS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.LATIAS, Species.LATIOS ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Latias or Mega Latios p.generateAndPopulateMoveset(); p.generateName(); })), [TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(signatureSpecies["STEVEN"], true).setBattleBgm("battle_hoenn_champion_g5").setMixedBattleBgm("battle_hoenn_champion_g6").setHasDouble("steven_wallace_double").setDoubleTrainerType(TrainerType.WALLACE).setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SKARMORY], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SKARMORY ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.METAGROSS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.METAGROSS ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Metagross p.generateAndPopulateMoveset(); p.generateName(); })), [TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(signatureSpecies["WALLACE"], true).setBattleBgm("battle_hoenn_champion_g5").setMixedBattleBgm("battle_hoenn_champion_g6").setHasDouble("wallace_steven_double").setDoubleTrainerType(TrainerType.STEVEN).setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PELIPPER], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PELIPPER ], TrainerSlot.TRAINER, true, p => { p.abilityIndex = 1; // Drizzle p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.SWAMPERT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.SWAMPERT ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Swampert p.generateAndPopulateMoveset(); p.generateName(); })), [TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(signatureSpecies["CYNTHIA"], false).setBattleBgm("battle_sinnoh_champion").setMixedBattleBgm("battle_sinnoh_champion") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SPIRITOMB], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SPIRITOMB ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.GARCHOMP], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GARCHOMP ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Garchomp p.generateAndPopulateMoveset(); p.generateName(); })), [TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(signatureSpecies["ALDER"], true).setHasDouble("alder_iris_double").setDoubleTrainerType(TrainerType.IRIS).setDoubleTitle("champion_double").setBattleBgm("battle_champion_alder").setMixedBattleBgm("battle_champion_alder") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BOUFFALANT, Species.BRAVIARY], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BOUFFALANT, Species.BRAVIARY ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })), [TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(signatureSpecies["IRIS"], false).setBattleBgm("battle_champion_iris").setMixedBattleBgm("battle_champion_iris").setHasDouble("iris_alder_double").setDoubleTrainerType(TrainerType.ALDER).setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.DRUDDIGON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.DRUDDIGON ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.LAPRAS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.LAPRAS ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // G-Max Lapras p.generateAndPopulateMoveset(); p.generateName(); })), [TrainerType.DIANTHA]: new TrainerConfig(++t).initForChampion(signatureSpecies["DIANTHA"], false).setMixedBattleBgm("battle_kalos_champion") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GOURGEIST], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GOURGEIST ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.GARDEVOIR], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.GARDEVOIR ], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Gardevoir p.generateAndPopulateMoveset(); p.generateName(); })), [TrainerType.HAU]: new TrainerConfig(++t).initForChampion(signatureSpecies["HAU"], true).setMixedBattleBgm("battle_alola_champion") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.ALOLA_RAICHU], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ALOLA_RAICHU ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })), [TrainerType.LEON]: new TrainerConfig(++t).initForChampion(signatureSpecies["LEON"], true).setMixedBattleBgm("battle_galar_champion") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.RILLABOOM, Species.CINDERACE, Species.INTELEON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.RILLABOOM, Species.CINDERACE, Species.INTELEON ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.CHARIZARD], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CHARIZARD ], TrainerSlot.TRAINER, true, p => { p.formIndex = 3; // G-Max Charizard p.generateAndPopulateMoveset(); p.generateName(); })), [TrainerType.GEETA]: new TrainerConfig(++t).initForChampion(signatureSpecies["GEETA"], false).setMixedBattleBgm("battle_champion_geeta") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.GLIMMORA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GLIMMORA ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })), [TrainerType.NEMONA]: new TrainerConfig(++t).initForChampion(signatureSpecies["NEMONA"], false).setMixedBattleBgm("battle_champion_nemona") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LYCANROC], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LYCANROC ], TrainerSlot.TRAINER, true, p => { p.formIndex = 0; // Midday form p.generateAndPopulateMoveset(); })), [TrainerType.KIERAN]: new TrainerConfig(++t).initForChampion(signatureSpecies["KIERAN"], true).setMixedBattleBgm("battle_champion_kieran") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.POLIWRATH, Species.POLITOED], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.POLIWRATH, Species.POLITOED ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); })), [TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setMixedBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL) .setModifierRewardFuncs(() => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE) - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.CHIKORITA, Species.CYNDAQUIL, Species.TOTODILE, Species.TREECKO, Species.TORCHIC, Species.MUDKIP, Species.TURTWIG, Species.CHIMCHAR, Species.PIPLUP, Species.SNIVY, Species.TEPIG, Species.OSHAWOTT, Species.CHESPIN, Species.FENNEKIN, Species.FROAKIE, Species.ROWLET, Species.LITTEN, Species.POPPLIO, Species.GROOKEY, Species.SCORBUNNY, Species.SOBBLE, Species.SPRIGATITO, Species.FUECOCO, Species.QUAXLY], TrainerSlot.TRAINER, true)) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEY, Species.HOOTHOOT, Species.TAILLOW, Species.STARLY, Species.PIDOVE, Species.FLETCHLING, Species.PIKIPEK, Species.ROOKIDEE, Species.WATTREL], TrainerSlot.TRAINER, true)), + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.CHIKORITA, Species.CYNDAQUIL, Species.TOTODILE, Species.TREECKO, Species.TORCHIC, Species.MUDKIP, Species.TURTWIG, Species.CHIMCHAR, Species.PIPLUP, Species.SNIVY, Species.TEPIG, Species.OSHAWOTT, Species.CHESPIN, Species.FENNEKIN, Species.FROAKIE, Species.ROWLET, Species.LITTEN, Species.POPPLIO, Species.GROOKEY, Species.SCORBUNNY, Species.SOBBLE, Species.SPRIGATITO, Species.FUECOCO, Species.QUAXLY ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEY, Species.HOOTHOOT, Species.TAILLOW, Species.STARLY, Species.PIDOVE, Species.FLETCHLING, Species.PIKIPEK, Species.ROOKIDEE, Species.WATTREL ], TrainerSlot.TRAINER, true)), [TrainerType.RIVAL_2]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setMoneyMultiplier(1.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setMixedBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL_2) .setModifierRewardFuncs(() => modifierTypes.EXP_SHARE) - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.IVYSAUR, Species.CHARMELEON, Species.WARTORTLE, Species.BAYLEEF, Species.QUILAVA, Species.CROCONAW, Species.GROVYLE, Species.COMBUSKEN, Species.MARSHTOMP, Species.GROTLE, Species.MONFERNO, Species.PRINPLUP, Species.SERVINE, Species.PIGNITE, Species.DEWOTT, Species.QUILLADIN, Species.BRAIXEN, Species.FROGADIER, Species.DARTRIX, Species.TORRACAT, Species.BRIONNE, Species.THWACKEY, Species.RABOOT, Species.DRIZZILE, Species.FLORAGATO, Species.CROCALOR, Species.QUAXWELL], TrainerSlot.TRAINER, true)) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOTTO, Species.HOOTHOOT, Species.TAILLOW, Species.STARAVIA, Species.TRANQUILL, Species.FLETCHINDER, Species.TRUMBEAK, Species.CORVISQUIRE, Species.WATTREL], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.IVYSAUR, Species.CHARMELEON, Species.WARTORTLE, Species.BAYLEEF, Species.QUILAVA, Species.CROCONAW, Species.GROVYLE, Species.COMBUSKEN, Species.MARSHTOMP, Species.GROTLE, Species.MONFERNO, Species.PRINPLUP, Species.SERVINE, Species.PIGNITE, Species.DEWOTT, Species.QUILLADIN, Species.BRAIXEN, Species.FROGADIER, Species.DARTRIX, Species.TORRACAT, Species.BRIONNE, Species.THWACKEY, Species.RABOOT, Species.DRIZZILE, Species.FLORAGATO, Species.CROCALOR, Species.QUAXWELL ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOTTO, Species.HOOTHOOT, Species.TAILLOW, Species.STARAVIA, Species.TRANQUILL, Species.FLETCHINDER, Species.TRUMBEAK, Species.CORVISQUIRE, Species.WATTREL ], TrainerSlot.TRAINER, true)) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)), [TrainerType.RIVAL_3]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setStaticParty().setMoneyMultiplier(1.5).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival").setMixedBattleBgm("battle_rival").setPartyTemplates(trainerPartyTemplates.RIVAL_3) - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], TrainerSlot.TRAINER, true)) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ], TrainerSlot.TRAINER, true)) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setSpeciesFilter(species => species.baseTotal >= 540), [TrainerType.RIVAL_4]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(1.75).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival_2").setMixedBattleBgm("battle_rival_2").setPartyTemplates(trainerPartyTemplates.RIVAL_4) - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], TrainerSlot.TRAINER, true)) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ], TrainerSlot.TRAINER, true)) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setSpeciesFilter(species => species.baseTotal >= 540) .setGenModifiersFunc(party => { const starter = party[0]; - return [modifierTypes.TERA_SHARD().generateType([], [starter.species.type1])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier]; // TODO: is the bang correct? + return [ modifierTypes.TERA_SHARD().generateType([], [ starter.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ]; // TODO: is the bang correct? }), [TrainerType.RIVAL_5]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm("battle_rival_3").setMixedBattleBgm("battle_rival_3").setPartyTemplates(trainerPartyTemplates.RIVAL_5) - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], TrainerSlot.TRAINER, true, + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ], TrainerSlot.TRAINER, true, p => p.setBoss(true, 2))) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL], TrainerSlot.TRAINER, true)) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ], TrainerSlot.TRAINER, true)) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setSpeciesFilter(species => species.baseTotal >= 540) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.RAYQUAZA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 3); p.pokeball = PokeballType.MASTER_BALL; p.shiny = true; @@ -1863,22 +1863,22 @@ export const trainerConfigs: TrainerConfigs = { })) .setGenModifiersFunc(party => { const starter = party[0]; - return [modifierTypes.TERA_SHARD().generateType([], [starter.species.type1])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier]; //TODO: is the bang correct? + return [ modifierTypes.TERA_SHARD().generateType([], [ starter.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ]; //TODO: is the bang correct? }), [TrainerType.RIVAL_6]: new TrainerConfig(++t).setName("Finn").setHasGenders("Ivy").setHasCharSprite().setTitle("Rival").setBoss().setStaticParty().setMoneyMultiplier(3).setEncounterBgm("final").setBattleBgm("battle_rival_3").setMixedBattleBgm("battle_rival_3").setPartyTemplates(trainerPartyTemplates.RIVAL_6) - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL], TrainerSlot.TRAINER, true, + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA, Species.RILLABOOM, Species.CINDERACE, Species.INTELEON, Species.MEOWSCARADA, Species.SKELEDIRGE, Species.QUAQUAVAL ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 3); p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL], TrainerSlot.TRAINER, true, + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.NOCTOWL, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON, Species.CORVIKNIGHT, Species.KILOWATTREL ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); })) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setSpeciesFilter(species => species.baseTotal >= 540) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.RAYQUAZA], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ], TrainerSlot.TRAINER, true, p => { p.setBoss(); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; @@ -1889,16 +1889,19 @@ export const trainerConfigs: TrainerConfigs = { })) .setGenModifiersFunc(party => { const starter = party[0]; - return [modifierTypes.TERA_SHARD().generateType([], [starter.species.type1])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier]; // TODO: is the bang correct? + return [ modifierTypes.TERA_SHARD().generateType([], [ starter.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(starter) as PersistentModifier ]; // TODO: is the bang correct? }), [TrainerType.ROCKET_BOSS_GIOVANNI_1]: new TrainerConfig(t = TrainerType.ROCKET_BOSS_GIOVANNI_1).setName("Giovanni").initForEvilTeamLeader("Rocket Boss", []).setMixedBattleBgm("battle_rocket_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.PERSIAN, Species.ALOLA_PERSIAN])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.DUGTRIO, Species.ALOLA_DUGTRIO])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.HONCHKROW])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.NIDOKING, Species.NIDOQUEEN])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.RHYPERIOR])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.KANGASKHAN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PERSIAN, Species.ALOLA_PERSIAN ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.gender = Gender.MALE; + })) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.DUGTRIO, Species.ALOLA_DUGTRIO ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.HONCHKROW ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.NIDOKING, Species.NIDOQUEEN ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.RHYPERIOR ])) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; @@ -1906,21 +1909,21 @@ export const trainerConfigs: TrainerConfigs = { p.generateName(); })), [TrainerType.ROCKET_BOSS_GIOVANNI_2]: new TrainerConfig(++t).setName("Giovanni").initForEvilTeamLeader("Rocket Boss", [], true).setMixedBattleBgm("battle_rocket_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.TYRANITAR, Species.IRON_THORNS], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.TYRANITAR, Species.IRON_THORNS ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.HIPPOWDON])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.EXCADRILL, Species.GARCHOMP])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.KANGASKHAN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.HIPPOWDON ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.EXCADRILL, Species.GARCHOMP ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.KANGASKHAN ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.formIndex = 1; // Mega Kangaskhan p.generateName(); })) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.GASTRODON, Species.SEISMITOAD], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.GASTRODON, Species.SEISMITOAD ], TrainerSlot.TRAINER, true, p => { //Storm Drain Gastrodon, Water Absorb Seismitoad if (p.species.speciesId === Species.GASTRODON) { p.abilityIndex = 0; @@ -1928,75 +1931,78 @@ export const trainerConfigs: TrainerConfigs = { p.abilityIndex = 2; } })) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.MEWTWO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.MEWTWO ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; })), [TrainerType.MAXIE]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss", []).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.MIGHTYENA])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.CROBAT, Species.GLISCOR])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.WEEZING, Species.GALAR_WEEZING])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.MAGMORTAR, Species.TORKOAL])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.FLYGON])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.CAMERUPT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.MIGHTYENA ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CROBAT, Species.GLISCOR ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WEEZING, Species.GALAR_WEEZING ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.MAGMORTAR, Species.TORKOAL ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.FLYGON ])) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.CAMERUPT ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.formIndex = 1; // Mega Camerupt p.generateName(); + p.gender = Gender.MALE; })), [TrainerType.MAXIE_2]: new TrainerConfig(++t).setName("Maxie").initForEvilTeamLeader("Magma Boss", [], true).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SOLROCK, Species.TYPHLOSION], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SOLROCK, Species.TYPHLOSION ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.TORKOAL, Species.NINETALES], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.TORKOAL, Species.NINETALES ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = 2; // Drought })) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SHIFTRY, Species.SCOVILLAIN], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SHIFTRY, Species.SCOVILLAIN ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = 0; // Chlorophyll })) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.GREAT_TUSK])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.CAMERUPT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GREAT_TUSK ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.CAMERUPT ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.formIndex = 1; // Mega Camerupt p.generateName(); + p.gender = Gender.MALE; })) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.GROUDON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GROUDON ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; })), [TrainerType.ARCHIE]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss", []).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.LINOONE])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.CROBAT, Species.PELIPPER])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.MUK, Species.ALOLA_MUK])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.TENTACRUEL])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.RELICANTH, Species.WAILORD])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.SHARPEDO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.LINOONE ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.CROBAT, Species.PELIPPER ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.MUK, Species.ALOLA_MUK ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.TENTACRUEL ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.RELICANTH, Species.WAILORD ])) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.SHARPEDO ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.formIndex = 1; // Mega Sharpedo p.generateName(); + p.gender = Gender.MALE; })), [TrainerType.ARCHIE_2]: new TrainerConfig(++t).setName("Archie").initForEvilTeamLeader("Aqua Boss", [], true).setMixedBattleBgm("battle_aqua_magma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.EMPOLEON, Species.LUDICOLO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.EMPOLEON, Species.LUDICOLO ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.POLITOED, Species.PELIPPER], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.POLITOED, Species.PELIPPER ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = 2; // Drizzle })) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.BEARTIC, Species.ARMALDO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.BEARTIC, Species.ARMALDO ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = 2; // Swift Swim })) @@ -2004,14 +2010,15 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.abilityIndex = 1; // Swift Swim })) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.SHARPEDO], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SHARPEDO ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.formIndex = 1; // Mega Sharpedo p.generateName(); + p.gender = Gender.MALE; })) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.KYOGRE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KYOGRE ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; @@ -2027,44 +2034,47 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; // Mega Houndoom p.generateName(); })) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.WEAVILE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.WEAVILE ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; + p.gender = Gender.MALE; })), [TrainerType.CYRUS_2]: new TrainerConfig(++t).setName("Cyrus").initForEvilTeamLeader("Galactic Boss", [], true).setMixedBattleBgm("battle_galactic_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.AZELF, Species.UXIE, Species.MESPRIT], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.AZELF, Species.UXIE, Species.MESPRIT ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); })) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.ELECTRODE, Species.HISUI_ELECTRODE])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SALAMENCE, Species.ROARING_MOON])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.HOUNDOOM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ELECTRODE, Species.HISUI_ELECTRODE ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SALAMENCE, Species.ROARING_MOON ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.HOUNDOOM ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; p.formIndex = 1; // Mega Houndoom p.generateName(); })) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.WEAVILE, Species.SNEASLER], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.WEAVILE, Species.SNEASLER ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; + p.gender = Gender.MALE; })) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.DARKRAI], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.DARKRAI ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; })), [TrainerType.GHETSIS]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss", []).setMixedBattleBgm("battle_plasma_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.COFAGRIGUS, Species.RUNERIGUS])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([Species.BOUFFALANT])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([Species.SEISMITOAD, Species.CARRACOSTA])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([Species.EELEKTROSS, Species.GALVANTULA])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([Species.VOLCARONA])) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.HYDREIGON], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.COFAGRIGUS, Species.RUNERIGUS ])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BOUFFALANT ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.SEISMITOAD, Species.CARRACOSTA ])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.EELEKTROSS, Species.GALVANTULA ])) + .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.VOLCARONA ])) + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.HYDREIGON ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; + p.gender = Gender.MALE; })), [TrainerType.GHETSIS_2]: new TrainerConfig(++t).setName("Ghetsis").initForEvilTeamLeader("Plasma Boss", [], true).setMixedBattleBgm("battle_plasma_boss").setVictoryBgm("victory_team_plasma") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.GENESECT ], TrainerSlot.TRAINER, true, p => { @@ -2084,8 +2094,13 @@ export const trainerConfigs: TrainerConfigs = { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; + if (p.species.speciesId === Species.HYDREIGON) { + p.gender = Gender.MALE; + } else if (p.species.speciesId === Species.IRON_JUGULIS) { + p.gender = Gender.GENDERLESS; + } })) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.KYUREM], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.KYUREM ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; @@ -2105,9 +2120,10 @@ export const trainerConfigs: TrainerConfigs = { p.pokeball = PokeballType.ULTRA_BALL; p.formIndex = 1; // Mega Gyarados p.generateName(); + p.gender = Gender.MALE; })), [TrainerType.LYSANDRE_2]: new TrainerConfig(++t).setName("Lysandre").initForEvilTeamLeader("Flare Boss", [], true).setMixedBattleBgm("battle_flare_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([Species.SCREAM_TAIL, Species.FLUTTER_MANE], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SCREAM_TAIL, Species.FLUTTER_MANE ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; @@ -2124,14 +2140,18 @@ export const trainerConfigs: TrainerConfigs = { p.pokeball = PokeballType.ULTRA_BALL; p.formIndex = 1; // Mega Gyardos p.generateName(); + p.gender = Gender.MALE; })) - .setPartyMemberFunc(5, getRandomPartyMemberFunc([Species.YVELTAL], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.YVELTAL ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; })), [TrainerType.LUSAMINE]: new TrainerConfig(++t).setName("Lusamine").initForEvilTeamLeader("Aether Boss", []).setMixedBattleBgm("battle_aether_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CLEFABLE ])) + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CLEFABLE ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.gender = Gender.FEMALE; + })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.LILLIGANT, Species.HISUI_LILLIGANT ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.MILOTIC, Species.PRIMARINA ])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GALAR_SLOWBRO, Species.GALAR_SLOWKING ])) @@ -2148,7 +2168,10 @@ export const trainerConfigs: TrainerConfigs = { p.pokeball = PokeballType.ROGUE_BALL; })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MILOTIC, Species.PRIMARINA ])) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.CLEFABLE ])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.CLEFABLE ], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.gender = Gender.FEMALE; + })) .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.STAKATAKA, Species.CELESTEELA, Species.GUZZLORD ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ROGUE_BALL; @@ -2181,7 +2204,7 @@ export const trainerConfigs: TrainerConfigs = { p.abilityIndex = 2; } })) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GALVANTULA, Species.VIKAVOLT])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.GALVANTULA, Species.VIKAVOLT ])) .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.PINSIR ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.formIndex = 1; // Mega Pinsir @@ -2191,6 +2214,7 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.GOLISOPOD ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); p.generateAndPopulateMoveset(); + p.gender = Gender.MALE; p.pokeball = PokeballType.ULTRA_BALL; })), [TrainerType.GUZMA_2]: new TrainerConfig(++t).setName("Guzma").initForEvilTeamLeader("Skull Boss", [], true).setMixedBattleBgm("battle_skull_boss").setVictoryBgm("victory_team_plasma") @@ -2198,6 +2222,7 @@ export const trainerConfigs: TrainerConfigs = { p.setBoss(true, 2); p.generateAndPopulateMoveset(); p.abilityIndex = 2; //Anticipation + p.gender = Gender.MALE; p.pokeball = PokeballType.ULTRA_BALL; })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.SCIZOR, Species.KLEAVOR ], TrainerSlot.TRAINER, true, p => { @@ -2239,6 +2264,7 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; // G-Max Copperajah p.generateName(); p.pokeball = PokeballType.ULTRA_BALL; + p.gender = Gender.FEMALE; })), [TrainerType.ROSE_2]: new TrainerConfig(++t).setName("Rose").initForEvilTeamLeader("Macro Boss", [], true).setMixedBattleBgm("battle_macro_boss").setVictoryBgm("victory_team_plasma") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.ARCHALUDON ], TrainerSlot.TRAINER, true, p => { @@ -2262,6 +2288,7 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; // G-Max Copperajah p.generateName(); p.pokeball = PokeballType.ULTRA_BALL; + p.gender = Gender.FEMALE; })), [TrainerType.PENNY]: new TrainerConfig(++t).setName("Cassiopeia").initForEvilTeamLeader("Star Boss", []).setMixedBattleBgm("battle_star_boss").setVictoryBgm("victory_team_plasma") .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VAPOREON, Species.JOLTEON, Species.FLAREON ])) @@ -2275,8 +2302,9 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = Utils.randSeedInt(5, 1); // Heat, Wash, Frost, Fan, or Mow })) .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); p.abilityIndex = 2; // Pixilate + p.generateAndPopulateMoveset(); + p.gender = Gender.FEMALE; })) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.EEVEE ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); @@ -2287,23 +2315,24 @@ export const trainerConfigs: TrainerConfigs = { })) .setGenModifiersFunc(party => { const teraPokemon = party[4]; - return [modifierTypes.TERA_SHARD().generateType([], [teraPokemon.species.type1])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier]; //TODO: is the bang correct? + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; //TODO: is the bang correct? }), [TrainerType.PENNY_2]: new TrainerConfig(++t).setName("Cassiopeia").initForEvilTeamLeader("Star Boss", [], true).setMixedBattleBgm("battle_star_boss").setVictoryBgm("victory_team_plasma") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); - p.formIndex = Utils.randSeedInt(5, 1); //Random Starmobile form + p.abilityIndex = 2; // Pixilate p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ULTRA_BALL; + p.gender = Gender.FEMALE; })) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.ENTEI, Species.RAIKOU, Species.SUICUNE ], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; })) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WALKING_WAKE, Species.GOUGING_FIRE, Species.RAGING_BOLT ])) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => { + .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => { + p.formIndex = Utils.randSeedInt(5, 1); //Random Starmobile form p.generateAndPopulateMoveset(); - p.abilityIndex = 2; // Pixilate + p.pokeball = PokeballType.ROGUE_BALL; })) .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.EEVEE ], TrainerSlot.TRAINER, true, p => { p.setBoss(true, 2); @@ -2318,8 +2347,8 @@ export const trainerConfigs: TrainerConfigs = { p.pokeball = PokeballType.MASTER_BALL; })) .setGenModifiersFunc(party => { - const teraPokemon = party[3]; - return [modifierTypes.TERA_SHARD().generateType([], [teraPokemon.species.type1])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier]; //TODO: is the bang correct? + const teraPokemon = party[0]; + return [ modifierTypes.TERA_SHARD().generateType([], [ teraPokemon.species.type1 ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(teraPokemon) as PersistentModifier ]; //TODO: is the bang correct? }), [TrainerType.BUCK]: new TrainerConfig(++t).setName("Buck").initForStatTrainer([], true) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.CLAYDOL ], TrainerSlot.TRAINER, true, p => { diff --git a/src/data/trainer-names.ts b/src/data/trainer-names.ts index 899702ff193..d075b7121f2 100644 --- a/src/data/trainer-names.ts +++ b/src/data/trainer-names.ts @@ -75,56 +75,56 @@ const trainerNameConfigs: TrainerNameConfigs = { }; export const trainerNamePools = { - [TrainerType.ACE_TRAINER]: [["Aaron", "Allen", "Blake", "Brian", "Gaven", "Jake", "Kevin", "Mike", "Nick", "Paul", "Ryan", "Sean", "Darin", "Albert", "Berke", "Clyde", "Edgar", "George", "Leroy", "Owen", "Parker", "Randall", "Ruben", "Samuel", "Vincent", "Warren", "Wilton", "Zane", "Alfred", "Braxton", "Felix", "Gerald", "Jonathan", "Leonel", "Marcel", "Mitchell", "Quincy", "Roderick", "Colby", "Rolando", "Yuji", "Abel", "Anton", "Arthur", "Cesar", "Dalton", "Dennis", "Ernest", "Garrett", "Graham", "Henry", "Isaiah", "Jonah", "Jose", "Keenan", "Micah", "Omar", "Quinn", "Rodolfo", "Saul", "Sergio", "Skylar", "Stefan", "Zachery", "Alton", "Arabella", "Bonita", "Cal", "Cody", "French", "Kobe", "Paulo", "Shaye", "Austin", "Beckett", "Charlie", "Corky", "David", "Dwayne", "Elmer", "Jesse", "Jared", "Johan", "Jordan", "Kipp", "Lou", "Terry", "Tom", "Webster", "Billy", "Doyle", "Enzio", "Geoff", "Grant", "Kelsey", "Miguel", "Pierce", "Ray", "Santino", "Shel", "Adelbert", "Bence", "Emil", "Evan", "Mathis", "Maxim", "Neil", "Rico", "Robbie", "Theo", "Viktor", "Benedict", "Cornelius", "Hisato", "Leopold", "Neville", "Vito", "Chase", "Cole", "Hiroshi", "Jackson", "Jim", "Kekoa", "Makana", "Yuki", "Elwood", "Seth", "Alvin", "Arjun", "Arnold", "Cameron", "Carl", "Carlton", "Christopher", "Dave", "Dax", "Dominic", "Edmund", "Finn", "Fred", "Garret", "Grayson", "Jace", "Jaxson", "Jay", "Jirard", "Johnson", "Kayden", "Kite", "Louis", "Mac", "Marty", "Percy", "Raymond", "Ronnie", "Satch", "Tim", "Zach", "Conner", "Vince", "Bedro", "Boda", "Botan", "Daras", "Dury", "Herton", "Rewn", "Stum", "Tock", "Trilo", "Berki", "Cruik", "Dazon", "Desid", "Dillot", "Farfin", "Forgon", "Hebel", "Morfon", "Moril", "Shadd", "Vanhub", "Bardo", "Carben", "Degin", "Gorps", "Klept", "Lask", "Malex", "Mopar", "Niled", "Noxon", "Teslor", "Tetil"], ["Beth", "Carol", "Cybil", "Emma", "Fran", "Gwen", "Irene", "Jenn", "Joyce", "Kate", "Kelly", "Lois", "Lola", "Megan", "Quinn", "Reena", "Cara", "Alexa", "Brooke", "Caroline", "Elaine", "Hope", "Jennifer", "Jody", "Julie", "Lori", "Mary", "Michelle", "Shannon", "Wendy", "Alexia", "Alicia", "Athena", "Carolina", "Cristin", "Darcy", "Dianne", "Halle", "Jazmyn", "Katelynn", "Keira", "Marley", "Allyson", "Kathleen", "Naomi", "Alyssa", "Ariana", "Brandi", "Breanna", "Brenda", "Brenna", "Catherine", "Clarice", "Dana", "Deanna", "Destiny", "Jamie", "Jasmin", "Kassandra", "Laura", "Maria", "Mariah", "Maya", "Meagan", "Mikayla", "Monique", "Natasha", "Olivia", "Sandra", "Savannah", "Sydney", "Moira", "Piper", "Salma", "Allison", "Beverly", "Cathy", "Cheyenne", "Clara", "Dara", "Eileen", "Glinda", "Junko", "Lena", "Lucille", "Mariana", "Olwen", "Shanta", "Stella", "Angi", "Belle", "Chandra", "Cora", "Eve", "Jacqueline", "Jeanne", "Juliet", "Kathrine", "Layla", "Lucca", "Melina", "Miki", "Nina", "Sable", "Shelly", "Summer", "Trish", "Vicki", "Alanza", "Cordelia", "Hilde", "Imelda", "Michele", "Mireille", "Claudia", "Constance", "Harriet", "Honor", "Melba", "Portia", "Alexis", "Angela", "Karla", "Lindsey", "Tori", "Sheri", "Jada", "Kailee", "Amanda", "Annie", "Kindra", "Kyla", "Sofia", "Yvette", "Becky", "Flora", "Gloria", "Buna", "Ferda", "Lehan", "Liqui", "Lomen", "Neira", "Atilo", "Detta", "Gilly", "Gosney", "Levens", "Moden", "Rask", "Rateis", "Rosno", "Tynan", "Veron", "Zoel", "Cida", "Dibsin", "Dodin", "Ebson", "Equin", "Flostin", "Gabsen", "Halsion", "Hileon", "Quelor", "Rapeel", "Roze", "Tensin"]], - [TrainerType.ARTIST]: [["Ismael", "William", "Horton", "Pierre", "Zach", "Gough", "Salvador", "Vincent", "Duncan"], ["Georgia"]], - [TrainerType.BACKERS]: [["Alf & Fred", "Hawk & Dar", "Joe & Ross", "Les & Web", "Masa & Yas", "Stu & Art"], ["Ai & Ciel", "Ami & Eira", "Cam & Abby", "Fey & Sue", "Kat & Phae", "Kay & Ali", "Ava & Aya", "Cleo & Rio", "May & Mal"]], - [TrainerType.BACKPACKER]: [["Alexander", "Carlos", "Herman", "Jerome", "Keane", "Kelsey", "Kiyo", "Michael", "Nate", "Peter", "Sam", "Stephen", "Talon", "Terrance", "Toru", "Waylon", "Boone", "Clifford", "Ivan", "Kendall", "Lowell", "Randall", "Reece", "Roland", "Shane", "Walt", "Farid", "Heike", "Joren", "Lane", "Roderick", "Darnell", "Deon", "Emory", "Graeme", "Grayson", "Aitor", "Alex", "Arturo", "Asier", "Jaime", "Jonathan", "Julio", "Kevin", "Kosuke", "Lander", "Markel", "Mateo", "Nil", "Pau", "Samuel"], ["Anna", "Corin", "Elaine", "Emi", "Jill", "Kumiko", "Liz", "Lois", "Lora", "Molly", "Patty", "Ruth", "Vicki", "Annie", "Blossom", "Clara", "Eileen", "Mae", "Myra", "Rachel", "Tami", "Ashley", "Mikiko", "Kiana", "Perdy", "Maria", "Yuho", "Peren", "Barbara", "Diane"]], - [TrainerType.BAKER]: ["Chris", "Jenn", "Lilly"], - [TrainerType.BEAUTY]: ["Cassie", "Julia", "Olivia", "Samantha", "Valerie", "Victoria", "Bridget", "Connie", "Jessica", "Johanna", "Melissa", "Sheila", "Shirley", "Tiffany", "Namiko", "Thalia", "Grace", "Lola", "Lori", "Maura", "Tamia", "Cyndy", "Devon", "Gabriella", "Harley", "Lindsay", "Nicola", "Callie", "Charlotte", "Kassandra", "December", "Fleming", "Nikola", "Aimee", "Anais", "Brigitte", "Cassandra", "Andrea", "Brittney", "Carolyn", "Krystal", "Alexis", "Alice", "Aina", "Anya", "Arianna", "Aubrey", "Beverly", "Camille", "Beauty", "Evette", "Hansol", "Haruka", "Jill", "Jo", "Lana", "Lois", "Lucy", "Mai", "Nickie", "Nicole", "Prita", "Rose", "Shelly", "Suzy", "Tessa", "Anita", "Alissa", "Rita", "Cudsy", "Eloff", "Miru", "Minot", "Nevah", "Niven", "Ogoin"], - [TrainerType.BIKER]: ["Charles", "Dwayne", "Glenn", "Harris", "Joel", "Riley", "Zeke", "Alex", "Billy", "Ernest", "Gerald", "Hideo", "Isaac", "Jared", "Jaren", "Jaxon", "Jordy", "Lao", "Lukas", "Malik", "Nikolas", "Ricardo", "Ruben", "Virgil", "William", "Aiden", "Dale", "Dan", "Jacob", "Markey", "Reese", "Teddy", "Theron", "Jeremy", "Morgann", "Phillip", "Philip", "Stanley", "Dillon"], - [TrainerType.BLACK_BELT]: [["Kenji", "Lao", "Lung", "Nob", "Wai", "Yoshi", "Atsushi", "Daisuke", "Hideki", "Hitoshi", "Kiyo", "Koichi", "Koji", "Yuji", "Cristian", "Rhett", "Takao", "Theodore", "Zander", "Aaron", "Hugh", "Mike", "Nicolas", "Shea", "Takashi", "Adam", "Carl", "Colby", "Darren", "David", "Davon", "Derek", "Eddie", "Gregory", "Griffin", "Jarrett", "Jeffery", "Kendal", "Kyle", "Luke", "Miles", "Nathaniel", "Philip", "Rafael", "Ray", "Ricky", "Sean", "Willie", "Ander", "Manford", "Benjamin", "Corey", "Edward", "Grant", "Jay", "Kendrew", "Kentaro", "Ryder", "Teppei", "Thomas", "Tyrone", "Andrey", "Donny", "Drago", "Gordon", "Grigor", "Jeriel", "Kenneth", "Martell", "Mathis", "Rich", "Rocky", "Rodrigo", "Wesley", "Zachery", "Alonzo", "Cadoc", "Gunnar", "Igor", "Killian", "Markus", "Ricardo", "Yanis", "Banting", "Clayton", "Duane", "Earl", "Greg", "Roy", "Terry", "Tracy", "Walter", "Alvaro", "Curtis", "Francis", "Ross", "Brice", "Cheng", "Dudley", "Eric", "Kano", "Masahiro", "Randy", "Ryuji", "Steve", "Tadashi", "Wong", "Yuen", "Brian", "Carter", "Reece", "Nick", "Yang"], ["Cora", "Cyndy", "Jill", "Laura", "Sadie", "Tessa", "Vivian", "Aisha", "Callie", "Danielle", "Helene", "Jocelyn", "Lilith", "Paula", "Reyna", "Helen", "Kelsey", "Tyler", "Amy", "Chandra", "Hillary", "Janie", "Lee", "Maggie", "Mikiko", "Miriam", "Sharon", "Susie", "Xiao", "Alize", "Azra", "Brenda", "Chalina", "Chan", "Glinda", "Maki", "Tia", "Tiffany", "Wendy", "Andrea", "Gabrielle", "Gerardine", "Hailey", "Hedvig", "Justine", "Kinsey", "Sigrid", "Veronique", "Tess"]], - [TrainerType.BREEDER]: [["Isaac", "Myles", "Salvadore", "Albert", "Kahlil", "Eustace", "Galen", "Owen", "Addison", "Marcus", "Foster", "Cory", "Glenn", "Jay", "Wesley", "William", "Adrian", "Bradley", "Jaime"], ["Allison", "Alize", "Bethany", "Lily", "Lydia", "Gabrielle", "Jayden", "Pat", "Veronica", "Amber", "Jennifer", "Kaylee", "Adelaide", "Brooke", "Ethel", "April", "Irene", "Magnolia", "Amala", "Mercy", "Amanda", "Ikue", "Savannah", "Yuka", "Chloe", "Debra", "Denise", "Elena"]], - [TrainerType.CLERK]: [["Chaz", "Clemens", "Doug", "Fredric", "Ivan", "Isaac", "Nelson", "Wade", "Warren", "Augustin", "Gilligan", "Cody", "Jeremy", "Shane", "Dugal", "Royce", "Ronald"], ["Alberta", "Ingrid", "Katie", "Piper", "Trisha", "Wren", "Britney", "Lana", "Jessica", "Kristen", "Michelle", "Gabrielle"]], - [TrainerType.CYCLIST]: [["Axel", "James", "John", "Ryan", "Hector", "Jeremiah"], ["Kayla", "Megan", "Nicole", "Rachel", "Krissa", "Adelaide"]], - [TrainerType.DANCER]: ["Brian", "Davey", "Dirk", "Edmond", "Mickey", "Raymond", "Cara", "Julia", "Maika", "Mireille", "Ronda", "Zoe"], - [TrainerType.DEPOT_AGENT]: ["Josh", "Hank", "Vincent"], - [TrainerType.DOCTOR]: [["Hank", "Jerry", "Jules", "Logan", "Wayne", "Braid", "Derek", "Heath", "Julius", "Kit", "Graham"], ["Kirsten", "Sachiko", "Shery", "Carol", "Dixie", "Mariah"]], - [TrainerType.FIREBREATHER]: ["Bill", "Burt", "Cliff", "Dick", "Lyle", "Ned", "Otis", "Ray", "Richard", "Walt"], - [TrainerType.FISHERMAN]: ["Andre", "Arnold", "Barney", "Chris", "Edgar", "Henry", "Jonah", "Justin", "Kyle", "Martin", "Marvin", "Ralph", "Raymond", "Scott", "Stephen", "Wilton", "Tully", "Andrew", "Barny", "Carter", "Claude", "Dale", "Elliot", "Eugene", "Ivan", "Ned", "Nolan", "Roger", "Ronald", "Wade", "Wayne", "Darian", "Kai", "Chip", "Hank", "Kaden", "Tommy", "Tylor", "Alec", "Brett", "Cameron", "Cody", "Cole", "Cory", "Erick", "George", "Joseph", "Juan", "Kenneth", "Luc", "Miguel", "Travis", "Walter", "Zachary", "Josh", "Gideon", "Kyler", "Liam", "Murphy", "Bruce", "Damon", "Devon", "Hubert", "Jones", "Lydon", "Mick", "Pete", "Sean", "Sid", "Vince", "Bucky", "Dean", "Eustace", "Kenzo", "Leroy", "Mack", "Ryder", "Ewan", "Finn", "Murray", "Seward", "Shad", "Wharton", "Finley", "Fisher", "Fisk", "River", "Sheaffer", "Timin", "Carl", "Ernest", "Hal", "Herbert", "Hisato", "Mike", "Vernon", "Harriet", "Marina", "Chase"], - [TrainerType.GUITARIST]: ["Anna", "Beverly", "January", "Tina", "Alicia", "Claudia", "Julia", "Lidia", "Mireia", "Noelia", "Sara", "Sheila", "Tatiana"], - [TrainerType.HARLEQUIN]: ["Charley", "Ian", "Jack", "Kerry", "Louis", "Pat", "Paul", "Rick", "Anders", "Clarence", "Gary"], - [TrainerType.HIKER]: ["Anthony", "Bailey", "Benjamin", "Daniel", "Erik", "Jim", "Kenny", "Leonard", "Michael", "Parry", "Phillip", "Russell", "Sidney", "Tim", "Timothy", "Alan", "Brice", "Clark", "Eric", "Lenny", "Lucas", "Mike", "Trent", "Devan", "Eli", "Marc", "Sawyer", "Allen", "Daryl", "Dudley", "Earl", "Franklin", "Jeremy", "Marcos", "Nob", "Oliver", "Wayne", "Alexander", "Damon", "Jonathan", "Justin", "Kevin", "Lorenzo", "Louis", "Maurice", "Nicholas", "Reginald", "Robert", "Theodore", "Bruce", "Clarke", "Devin", "Dwight", "Edwin", "Eoin", "Noland", "Russel", "Andy", "Bret", "Darrell", "Gene", "Hardy", "Hugh", "Jebediah", "Jeremiah", "Kit", "Neil", "Terrell", "Don", "Doug", "Hunter", "Jared", "Jerome", "Keith", "Manuel", "Markus", "Otto", "Shelby", "Stephen", "Teppei", "Tobias", "Wade", "Zaiem", "Aaron", "Alain", "Bergin", "Bernard", "Brent", "Corwin", "Craig", "Delmon", "Dunstan", "Orestes", "Ross", "Davian", "Calhoun", "David", "Gabriel", "Ryan", "Thomas", "Travis", "Zachary", "Anuhea", "Barnaby", "Claus", "Collin", "Colson", "Dexter", "Dillan", "Eugine", "Farkas", "Hisato", "Julius", "Kenji", "Irwin", "Lionel", "Paul", "Richter", "Valentino", "Donald", "Douglas", "Kevyn", "Chester"], //["Angela","Carla","Celia","Daniela","Estela","Fatima","Helena","Leire","Lucia","Luna","Manuela","Mar","Marina","Miyu","Nancy","Nerea","Paula","Rocio","Yanira"] - [TrainerType.HOOLIGANS]: ["Jim & Cas", "Rob & Sal"], - [TrainerType.HOOPSTER]: ["Bobby", "John", "Lamarcus", "Derrick", "Nicolas"], - [TrainerType.INFIELDER]: ["Alex", "Connor", "Todd"], - [TrainerType.JANITOR]: ["Caleb", "Geoff", "Brady", "Felix", "Orville", "Melvin", "Shawn"], - [TrainerType.LINEBACKER]: ["Bob", "Dan", "Jonah"], - [TrainerType.MAID]: ["Belinda", "Sophie", "Emily", "Elena", "Clare", "Alica", "Tanya", "Tammy"], - [TrainerType.MUSICIAN]: ["Boris", "Preston", "Charles", "Clyde", "Vincent", "Dalton", "Kirk", "Shawn", "Fabian", "Fernando", "Joseph", "Marcos", "Arturo", "Jerry", "Lonnie", "Tony"], - [TrainerType.NURSERY_AIDE]: ["Autumn", "Briana", "Leah", "Miho", "Ethel", "Hollie", "Ilse", "June", "Kimya", "Rosalyn"], - [TrainerType.OFFICER]: ["Dirk", "Keith", "Alex", "Bobby", "Caleb", "Danny", "Dylan", "Thomas", "Daniel", "Jeff", "Braven", "Dell", "Neagle", "Haruki", "Mitchell", "Raymond"], - [TrainerType.PARASOL_LADY]: ["Angelica", "Clarissa", "Madeline", "Akari", "Annabell", "Kayley", "Rachel", "Alexa", "Sabrina", "April", "Gwyneth", "Laura", "Lumi", "Mariah", "Melita", "Nicole", "Tihana", "Ingrid", "Tyra"], - [TrainerType.PILOT]: ["Chase", "Leonard", "Ted", "Elron", "Ewing", "Flynn", "Winslow"], - [TrainerType.POKEFAN]: [["Alex", "Allan", "Brandon", "Carter", "Colin", "Derek", "Jeremy", "Joshua", "Rex", "Robert", "Trevor", "William", "Colton", "Miguel", "Francisco", "Kaleb", "Leonard", "Boone", "Elliot", "Jude", "Norbert", "Corey", "Gabe", "Baxter"], ["Beverly", "Georgia", "Jaime", "Ruth", "Isabel", "Marissa", "Vanessa", "Annika", "Bethany", "Kimberly", "Meredith", "Rebekah", "Eleanor", "Darcy", "Lydia", "Sachiko", "Abigail", "Agnes", "Lydie", "Roisin", "Tara", "Carmen", "Janet"]], - [TrainerType.PRESCHOOLER]: [["Billy", "Doyle", "Evan", "Homer", "Tully", "Albert", "Buster", "Greg", "Ike", "Jojo", "Tyrone", "Adrian", "Oliver", "Hayden", "Hunter", "Kaleb", "Liam", "Dylan"], ["Juliet", "Mia", "Sarah", "Wendy", "Winter", "Chrissy", "Eva", "Lin", "Samantha", "Ella", "Lily", "Natalie", "Ailey", "Hannah", "Malia", "Kindra", "Nancy"]], - [TrainerType.PSYCHIC]: [["Fidel", "Franklin", "Gilbert", "Greg", "Herman", "Jared", "Mark", "Nathan", "Norman", "Phil", "Richard", "Rodney", "Cameron", "Edward", "Fritz", "Joshua", "Preston", "Virgil", "William", "Alvaro", "Blake", "Cedric", "Keenan", "Nicholas", "Dario", "Johan", "Lorenzo", "Tyron", "Bryce", "Corbin", "Deandre", "Elijah", "Kody", "Landon", "Maxwell", "Mitchell", "Sterling", "Eli", "Nelson", "Vernon", "Gaven", "Gerard", "Low", "Micki", "Perry", "Rudolf", "Tommy", "Al", "Nandor", "Tully", "Arthur", "Emanuel", "Franz", "Harry", "Paschal", "Robert", "Sayid", "Angelo", "Anton", "Arin", "Avery", "Danny", "Frasier", "Harrison", "Jaime", "Ross", "Rui", "Vlad", "Mason"], ["Alexis", "Hannah", "Jacki", "Jaclyn", "Kayla", "Maura", "Samantha", "Alix", "Brandi", "Edie", "Macey", "Mariella", "Marlene", "Laura", "Rodette", "Abigail", "Brittney", "Chelsey", "Daisy", "Desiree", "Kendra", "Lindsey", "Rachael", "Valencia", "Belle", "Cybil", "Doreen", "Dua", "Future", "Lin", "Madhu", "Alia", "Ena", "Joyce", "Lynette", "Olesia", "Sarah"]], - [TrainerType.RANGER]: [["Carlos", "Jackson", "Sebastian", "Gav", "Lorenzo", "Logan", "Nicolas", "Trenton", "Deshawn", "Dwayne", "Jeffery", "Kyler", "Taylor", "Alain", "Claude", "Crofton", "Forrest", "Harry", "Jaden", "Keith", "Lewis", "Miguel", "Pedro", "Ralph", "Richard", "Bret", "Daryl", "Eddie", "Johan", "Leaf", "Louis", "Maxwell", "Parker", "Rick", "Steve", "Bjorn", "Chaise", "Dean", "Lee", "Maurice", "Nash", "Ralf", "Reed", "Shinobu", "Silas"], ["Catherine", "Jenna", "Sophia", "Merdith", "Nora", "Beth", "Chelsea", "Katelyn", "Madeline", "Allison", "Ashlee", "Felicia", "Krista", "Annie", "Audra", "Brenda", "Chloris", "Eliza", "Heidi", "Irene", "Mary", "Mylene", "Shanti", "Shelly", "Thalia", "Anja", "Briana", "Dianna", "Elaine", "Elle", "Hillary", "Katie", "Lena", "Lois", "Malory", "Melita", "Mikiko", "Naoko", "Serenity", "Ambre", "Brooke", "Clementine", "Melina", "Petra", "Twiggy"]], - [TrainerType.RICH]: [["Alfred", "Edward", "Gregory", "Preston", "Thomas", "Tucker", "Walter", "Clifford", "Everett", "Micah", "Nate", "Pierre", "Terrance", "Arthur", "Brooks", "Emanuel", "Lamar", "Jeremy", "Leonardo", "Milton", "Frederic", "Renaud", "Robert", "Yan", "Daniel", "Sheldon", "Stonewall", "Gerald", "Ronald", "Smith", "Stanley", "Reginald", "Orson", "Wilco", "Caden", "Glenn"], ["Rebecca", "Reina", "Cassandra", "Emilia", "Grace", "Marian", "Elizabeth", "Kathleen", "Sayuri", "Caroline", "Judy"]], - [TrainerType.RICH_KID]: [["Garret", "Winston", "Dawson", "Enrique", "Jason", "Roman", "Trey", "Liam", "Anthony", "Brad", "Cody", "Manuel", "Martin", "Pierce", "Rolan", "Keenan", "Filbert", "Antoin", "Cyus", "Diek", "Dugo", "Flitz", "Jurek", "Lond", "Perd", "Quint", "Basto", "Benit", "Brot", "Denc", "Guyit", "Marcon", "Perc", "Puros", "Roex", "Sainz", "Symin", "Tark", "Venak"], ["Anette", "Brianna", "Cindy", "Colleen", "Daphne", "Elizabeth", "Naomi", "Sarah", "Charlotte", "Gillian", "Jacki", "Lady", "Melissa", "Celeste", "Colette", "Elizandra", "Isabel", "Lynette", "Magnolia", "Sophie", "Lina", "Dulcie", "Auro", "Brin", "Caril", "Eloos", "Gwin", "Illa", "Kowly", "Rima", "Ristin", "Vesey", "Brena", "Deasy", "Denslon", "Kylet", "Nemi", "Rene", "Sanol", "Stouner", "Sturk", "Talmen", "Zoila"]], - [TrainerType.ROUGHNECK]: ["Camron", "Corey", "Gabriel", "Isaiah", "Jamal", "Koji", "Luke", "Paxton", "Raul", "Zeek", "Kirby", "Chance", "Dave", "Fletcher", "Johnny", "Reese", "Joey", "Ricky", "Silvester", "Martin"], - [TrainerType.SAILOR]: ["Alberto", "Bost", "Brennan", "Brenden", "Claude", "Cory", "Damian", "Dirk", "Duncan", "Dwayne", "Dylan", "Eddie", "Edmond", "Elijah", "Ernest", "Eugene", "Garrett", "Golos", "Gratin", "Grestly", "Harry", "Hols", "Hudson", "Huey", "Jebol", "Jeff", "Leonald", "Luther", "Kelvin", "Kenneth", "Kent", "Knook", "Marc", "Mifis", "Monar", "Morkor", "Ordes", "Oxlin", "Parker", "Paul", "Philip", "Roberto", "Samson", "Skyler", "Stanly", "Tebu", "Terrell", "Trevor", "Yasu", "Zachariah"], - [TrainerType.SCIENTIST]: [["Jed", "Marc", "Mitch", "Rich", "Ross", "Beau", "Braydon", "Connor", "Ed", "Ivan", "Jerry", "Jose", "Joshua", "Parker", "Rodney", "Taylor", "Ted", "Travis", "Zackery", "Darrius", "Emilio", "Fredrick", "Shaun", "Stefano", "Travon", "Daniel", "Garett", "Gregg", "Linden", "Lowell", "Trenton", "Dudley", "Luke", "Markus", "Nathan", "Orville", "Randall", "Ron", "Ronald", "Simon", "Steve", "William", "Franklin", "Clarke", "Jacques", "Terrance", "Ernst", "Justus", "Ikaika", "Jayson", "Kyle", "Reid", "Tyrone", "Adam", "Albert", "Alphonse", "Cory", "Donnie", "Elton", "Francis", "Gordon", "Herbert", "Humphrey", "Jordan", "Julian", "Keaton", "Levi", "Melvin", "Murray", "West", "Craig", "Coren", "Dubik", "Kotan", "Lethco", "Mante", "Mort", "Myron", "Odlow", "Ribek", "Roeck", "Vogi", "Vonder", "Zogo", "Doimo", "Doton", "Durel", "Hildon", "Kukla", "Messa", "Nanot", "Platen", "Raburn", "Reman", "Acrod", "Coffy", "Elrok", "Foss", "Hardig", "Hombol", "Hospel", "Kaller", "Klots", "Krilok", "Limar", "Loket", "Mesak", "Morbit", "Newin", "Orill", "Tabor", "Tekot"], ["Blythe", "Chan", "Kathrine", "Marie", "Maria", "Naoko", "Samantha", "Satomi", "Shannon", "Athena", "Caroline", "Lumi", "Lumina", "Marissa", "Sonia"]], - [TrainerType.SMASHER]: ["Aspen", "Elena", "Mari", "Amy", "Lizzy"], - [TrainerType.SNOW_WORKER]: [["Braden", "Brendon", "Colin", "Conrad", "Dillan", "Gary", "Gerardo", "Holden", "Jackson", "Mason", "Quentin", "Willy", "Noel", "Arnold", "Brady", "Brand", "Cairn", "Cliff", "Don", "Eddie", "Felix", "Filipe", "Glenn", "Gus", "Heath", "Matthew", "Patton", "Rich", "Rob", "Ryan", "Scott", "Shelby", "Sterling", "Tyler", "Victor", "Zack", "Friedrich", "Herman", "Isaac", "Leo", "Maynard", "Mitchell", "Morgann", "Nathan", "Niel", "Pasqual", "Paul", "Tavarius", "Tibor", "Dimitri", "Narek", "Yusif", "Frank", "Jeff", "Vaclav", "Ovid", "Francis", "Keith", "Russel", "Sangon", "Toway", "Bomber", "Chean", "Demit", "Hubor", "Kebile", "Laber", "Ordo", "Retay", "Ronix", "Wagel", "Dobit", "Kaster", "Lobel", "Releo", "Saken", "Rustix"], ["Georgia", "Sandra", "Yvonne"]], - [TrainerType.STRIKER]: ["Marco", "Roberto", "Tony"], - [TrainerType.SCHOOL_KID]: [["Alan", "Billy", "Chad", "Danny", "Dudley", "Jack", "Joe", "Johnny", "Kipp", "Nate", "Ricky", "Tommy", "Jerry", "Paul", "Ted", "Chance", "Esteban", "Forrest", "Harrison", "Connor", "Sherman", "Torin", "Travis", "Al", "Carter", "Edgar", "Jem", "Sammy", "Shane", "Shayne", "Alvin", "Keston", "Neil", "Seymour", "William", "Carson", "Clark", "Nolan"], ["Georgia", "Karen", "Meiko", "Christine", "Mackenzie", "Tiera", "Ann", "Gina", "Lydia", "Marsha", "Millie", "Sally", "Serena", "Silvia", "Alberta", "Cassie", "Mara", "Rita", "Georgie", "Meena", "Nitzel"]], - [TrainerType.SWIMMER]: [["Berke", "Cameron", "Charlie", "George", "Harold", "Jerome", "Kirk", "Mathew", "Parker", "Randall", "Seth", "Simon", "Tucker", "Austin", "Barry", "Chad", "Cody", "Darrin", "David", "Dean", "Douglas", "Franklin", "Gilbert", "Herman", "Jack", "Luis", "Matthew", "Reed", "Richard", "Rodney", "Roland", "Spencer", "Stan", "Tony", "Clarence", "Declan", "Dominik", "Harrison", "Kevin", "Leonardo", "Nolen", "Pete", "Santiago", "Axle", "Braden", "Finn", "Garrett", "Mymo", "Reece", "Samir", "Toby", "Adrian", "Colton", "Dillon", "Erik", "Evan", "Francisco", "Glenn", "Kurt", "Oscar", "Ricardo", "Sam", "Sheltin", "Troy", "Vincent", "Wade", "Wesley", "Duane", "Elmo", "Esteban", "Frankie", "Ronald", "Tyson", "Bart", "Matt", "Tim", "Wright", "Jeffery", "Kyle", "Alessandro", "Estaban", "Kieran", "Ramses", "Casey", "Dakota", "Jared", "Kalani", "Keoni", "Lawrence", "Logan", "Robert", "Roddy", "Yasu", "Derek", "Jacob", "Bruce", "Clayton"], ["Briana", "Dawn", "Denise", "Diana", "Elaine", "Kara", "Kaylee", "Lori", "Nicole", "Nikki", "Paula", "Susie", "Wendy", "Alice", "Beth", "Beverly", "Brenda", "Dana", "Debra", "Grace", "Jenny", "Katie", "Laurel", "Linda", "Missy", "Sharon", "Tanya", "Tara", "Tisha", "Carlee", "Imani", "Isabelle", "Kyla", "Sienna", "Abigail", "Amara", "Anya", "Connie", "Maria", "Melissa", "Nora", "Shirley", "Shania", "Tiffany", "Aubree", "Cassandra", "Claire", "Crystal", "Erica", "Gabrielle", "Haley", "Jessica", "Joanna", "Lydia", "Mallory", "Mary", "Miranda", "Paige", "Sophia", "Vanessa", "Chelan", "Debbie", "Joy", "Kendra", "Leona", "Mina", "Caroline", "Joyce", "Larissa", "Rebecca", "Tyra", "Dara", "Desiree", "Kaoru", "Ruth", "Coral", "Genevieve", "Isla", "Marissa", "Romy", "Sheryl", "Alexandria", "Alicia", "Chelsea", "Jade", "Kelsie", "Laura", "Portia", "Shelby", "Sara", "Tiare", "Kyra", "Natasha", "Layla", "Scarlett", "Cora"]], - [TrainerType.TWINS]: ["Amy & May", "Jo & Zoe", "Meg & Peg", "Ann & Anne", "Lea & Pia", "Amy & Liv", "Gina & Mia", "Miu & Yuki", "Tori & Tia", "Eli & Anne", "Jen & Kira", "Joy & Meg", "Kiri & Jan", "Miu & Mia", "Emma & Lil", "Liv & Liz", "Teri & Tia", "Amy & Mimi", "Clea & Gil", "Day & Dani", "Kay & Tia", "Tori & Til", "Saya & Aya", "Emy & Lin", "Kumi & Amy", "Mayo & May", "Ally & Amy", "Lia & Lily", "Rae & Ula", "Sola & Ana", "Tara & Val", "Faith & Joy", "Nana & Nina"], - [TrainerType.VETERAN]: [["Armando", "Brenden", "Brian", "Clayton", "Edgar", "Emanuel", "Grant", "Harlan", "Terrell", "Arlen", "Chester", "Hugo", "Martell", "Ray", "Shaun", "Abraham", "Carter", "Claude", "Jerry", "Lucius", "Murphy", "Rayne", "Ron", "Sinan", "Sterling", "Vincent", "Zach", "Gerard", "Gilles", "Louis", "Timeo", "Akira", "Don", "Eric", "Harry", "Leon", "Roger", "Angus", "Aristo", "Brone", "Johnny"], ["Julia", "Karla", "Kim", "Sayuri", "Tiffany", "Cathy", "Cecile", "Chloris", "Denae", "Gina", "Maya", "Oriana", "Portia", "Rhona", "Rosaline", "Catrina", "Inga", "Trisha", "Heather", "Lynn", "Sheri", "Alonsa", "Ella", "Leticia", "Kiara"]], - [TrainerType.WAITER]: [["Bert", "Clint", "Maxwell", "Lou"], ["Kati", "Aurora", "Bonita", "Flo", "Tia", "Jan", "Olwen", "Paget", "Paula", "Talia"]], - [TrainerType.WORKER]: [["Braden", "Brendon", "Colin", "Conrad", "Dillan", "Gary", "Gerardo", "Holden", "Jackson", "Mason", "Quentin", "Willy", "Noel", "Arnold", "Brady", "Brand", "Cairn", "Cliff", "Don", "Eddie", "Felix", "Filipe", "Glenn", "Gus", "Heath", "Matthew", "Patton", "Rich", "Rob", "Ryan", "Scott", "Shelby", "Sterling", "Tyler", "Victor", "Zack", "Friedrich", "Herman", "Isaac", "Leo", "Maynard", "Mitchell", "Morgann", "Nathan", "Niel", "Pasqual", "Paul", "Tavarius", "Tibor", "Dimitri", "Narek", "Yusif", "Frank", "Jeff", "Vaclav", "Ovid", "Francis", "Keith", "Russel", "Sangon", "Toway", "Bomber", "Chean", "Demit", "Hubor", "Kebile", "Laber", "Ordo", "Retay", "Ronix", "Wagel", "Dobit", "Kaster", "Lobel", "Releo", "Saken", "Rustix"], ["Georgia", "Sandra", "Yvonne"]], - [TrainerType.YOUNGSTER]: [["Albert", "Gordon", "Ian", "Jason", "Jimmy", "Mikey", "Owen", "Samuel", "Warren", "Allen", "Ben", "Billy", "Calvin", "Dillion", "Eddie", "Joey", "Josh", "Neal", "Timmy", "Tommy", "Breyden", "Deandre", "Demetrius", "Dillon", "Jaylen", "Johnson", "Shigenobu", "Chad", "Cole", "Cordell", "Dan", "Dave", "Destin", "Nash", "Tyler", "Yasu", "Austin", "Dallas", "Darius", "Donny", "Jonathon", "Logan", "Michael", "Oliver", "Sebastian", "Tristan", "Wayne", "Norman", "Roland", "Regis", "Abe", "Astor", "Keita", "Kenneth", "Kevin", "Kyle", "Lester", "Masao", "Nicholas", "Parker", "Wes", "Zachary", "Cody", "Henley", "Jaye", "Karl", "Kenny", "Masahiro", "Pedro", "Petey", "Sinclair", "Terrell", "Waylon", "Aidan", "Anthony", "David", "Jacob", "Jayden", "Cutler", "Ham", "Caleb", "Kai", "Honus", "Kenway", "Bret", "Chris", "Cid", "Dennis", "Easton", "Ken", "Robby", "Ronny", "Shawn", "Benjamin", "Jake", "Travis", "Adan", "Aday", "Beltran", "Elian", "Hernan", "Julen", "Luka", "Roi", "Bernie", "Dustin", "Jonathan", "Wyatt"], ["Alice", "Bridget", "Carrie", "Connie", "Dana", "Ellen", "Krise", "Laura", "Linda", "Michelle", "Shannon", "Andrea", "Crissy", "Janice", "Robin", "Sally", "Tiana", "Haley", "Ali", "Ann", "Dalia", "Dawn", "Iris", "Joana", "Julia", "Kay", "Lisa", "Megan", "Mikaela", "Miriam", "Paige", "Reli", "Blythe", "Briana", "Caroline", "Cassidy", "Kaitlin", "Madeline", "Molly", "Natalie", "Samantha", "Sarah", "Cathy", "Dye", "Eri", "Eva", "Fey", "Kara", "Lurleen", "Maki", "Mali", "Maya", "Miki", "Sibyl", "Daya", "Diana", "Flo", "Helia", "Henrietta", "Isabel", "Mai", "Persephone", "Serena", "Anna", "Charlotte", "Elin", "Elsa", "Lise", "Sara", "Suzette", "Audrey", "Emmy", "Isabella", "Madison", "Rika", "Rylee", "Salla", "Ellie", "Alexandra", "Amy", "Lass", "Brittany", "Chel", "Cindy", "Dianne", "Emily", "Emma", "Evelyn", "Hana", "Harleen", "Hazel", "Jocelyn", "Katrina", "Kimberly", "Lina", "Marge", "Mila", "Mizuki", "Rena", "Sal", "Satoko", "Summer", "Tomoe", "Vicky", "Yue", "Yumi", "Lauren", "Rei", "Riley", "Lois", "Nancy", "Tammy", "Terry"]], - [TrainerType.HEX_MANIAC]: ["Kindra", "Patricia", "Tammy", "Tasha", "Valerie", "Alaina", "Kathleen", "Leah", "Makie", "Sylvia", "Anina", "Arachna", "Carrie", "Desdemona", "Josette", "Luna", "Melanie", "Osanna", "Raziah"], + [TrainerType.ACE_TRAINER]: [[ "Aaron", "Allen", "Blake", "Brian", "Gaven", "Jake", "Kevin", "Mike", "Nick", "Paul", "Ryan", "Sean", "Darin", "Albert", "Berke", "Clyde", "Edgar", "George", "Leroy", "Owen", "Parker", "Randall", "Ruben", "Samuel", "Vincent", "Warren", "Wilton", "Zane", "Alfred", "Braxton", "Felix", "Gerald", "Jonathan", "Leonel", "Marcel", "Mitchell", "Quincy", "Roderick", "Colby", "Rolando", "Yuji", "Abel", "Anton", "Arthur", "Cesar", "Dalton", "Dennis", "Ernest", "Garrett", "Graham", "Henry", "Isaiah", "Jonah", "Jose", "Keenan", "Micah", "Omar", "Quinn", "Rodolfo", "Saul", "Sergio", "Skylar", "Stefan", "Zachery", "Alton", "Arabella", "Bonita", "Cal", "Cody", "French", "Kobe", "Paulo", "Shaye", "Austin", "Beckett", "Charlie", "Corky", "David", "Dwayne", "Elmer", "Jesse", "Jared", "Johan", "Jordan", "Kipp", "Lou", "Terry", "Tom", "Webster", "Billy", "Doyle", "Enzio", "Geoff", "Grant", "Kelsey", "Miguel", "Pierce", "Ray", "Santino", "Shel", "Adelbert", "Bence", "Emil", "Evan", "Mathis", "Maxim", "Neil", "Rico", "Robbie", "Theo", "Viktor", "Benedict", "Cornelius", "Hisato", "Leopold", "Neville", "Vito", "Chase", "Cole", "Hiroshi", "Jackson", "Jim", "Kekoa", "Makana", "Yuki", "Elwood", "Seth", "Alvin", "Arjun", "Arnold", "Cameron", "Carl", "Carlton", "Christopher", "Dave", "Dax", "Dominic", "Edmund", "Finn", "Fred", "Garret", "Grayson", "Jace", "Jaxson", "Jay", "Jirard", "Johnson", "Kayden", "Kite", "Louis", "Mac", "Marty", "Percy", "Raymond", "Ronnie", "Satch", "Tim", "Zach", "Conner", "Vince", "Bedro", "Boda", "Botan", "Daras", "Dury", "Herton", "Rewn", "Stum", "Tock", "Trilo", "Berki", "Cruik", "Dazon", "Desid", "Dillot", "Farfin", "Forgon", "Hebel", "Morfon", "Moril", "Shadd", "Vanhub", "Bardo", "Carben", "Degin", "Gorps", "Klept", "Lask", "Malex", "Mopar", "Niled", "Noxon", "Teslor", "Tetil" ], [ "Beth", "Carol", "Cybil", "Emma", "Fran", "Gwen", "Irene", "Jenn", "Joyce", "Kate", "Kelly", "Lois", "Lola", "Megan", "Quinn", "Reena", "Cara", "Alexa", "Brooke", "Caroline", "Elaine", "Hope", "Jennifer", "Jody", "Julie", "Lori", "Mary", "Michelle", "Shannon", "Wendy", "Alexia", "Alicia", "Athena", "Carolina", "Cristin", "Darcy", "Dianne", "Halle", "Jazmyn", "Katelynn", "Keira", "Marley", "Allyson", "Kathleen", "Naomi", "Alyssa", "Ariana", "Brandi", "Breanna", "Brenda", "Brenna", "Catherine", "Clarice", "Dana", "Deanna", "Destiny", "Jamie", "Jasmin", "Kassandra", "Laura", "Maria", "Mariah", "Maya", "Meagan", "Mikayla", "Monique", "Natasha", "Olivia", "Sandra", "Savannah", "Sydney", "Moira", "Piper", "Salma", "Allison", "Beverly", "Cathy", "Cheyenne", "Clara", "Dara", "Eileen", "Glinda", "Junko", "Lena", "Lucille", "Mariana", "Olwen", "Shanta", "Stella", "Angi", "Belle", "Chandra", "Cora", "Eve", "Jacqueline", "Jeanne", "Juliet", "Kathrine", "Layla", "Lucca", "Melina", "Miki", "Nina", "Sable", "Shelly", "Summer", "Trish", "Vicki", "Alanza", "Cordelia", "Hilde", "Imelda", "Michele", "Mireille", "Claudia", "Constance", "Harriet", "Honor", "Melba", "Portia", "Alexis", "Angela", "Karla", "Lindsey", "Tori", "Sheri", "Jada", "Kailee", "Amanda", "Annie", "Kindra", "Kyla", "Sofia", "Yvette", "Becky", "Flora", "Gloria", "Buna", "Ferda", "Lehan", "Liqui", "Lomen", "Neira", "Atilo", "Detta", "Gilly", "Gosney", "Levens", "Moden", "Rask", "Rateis", "Rosno", "Tynan", "Veron", "Zoel", "Cida", "Dibsin", "Dodin", "Ebson", "Equin", "Flostin", "Gabsen", "Halsion", "Hileon", "Quelor", "Rapeel", "Roze", "Tensin" ]], + [TrainerType.ARTIST]: [[ "Ismael", "William", "Horton", "Pierre", "Zach", "Gough", "Salvador", "Vincent", "Duncan" ], [ "Georgia" ]], + [TrainerType.BACKERS]: [[ "Alf & Fred", "Hawk & Dar", "Joe & Ross", "Les & Web", "Masa & Yas", "Stu & Art" ], [ "Ai & Ciel", "Ami & Eira", "Cam & Abby", "Fey & Sue", "Kat & Phae", "Kay & Ali", "Ava & Aya", "Cleo & Rio", "May & Mal" ]], + [TrainerType.BACKPACKER]: [[ "Alexander", "Carlos", "Herman", "Jerome", "Keane", "Kelsey", "Kiyo", "Michael", "Nate", "Peter", "Sam", "Stephen", "Talon", "Terrance", "Toru", "Waylon", "Boone", "Clifford", "Ivan", "Kendall", "Lowell", "Randall", "Reece", "Roland", "Shane", "Walt", "Farid", "Heike", "Joren", "Lane", "Roderick", "Darnell", "Deon", "Emory", "Graeme", "Grayson", "Aitor", "Alex", "Arturo", "Asier", "Jaime", "Jonathan", "Julio", "Kevin", "Kosuke", "Lander", "Markel", "Mateo", "Nil", "Pau", "Samuel" ], [ "Anna", "Corin", "Elaine", "Emi", "Jill", "Kumiko", "Liz", "Lois", "Lora", "Molly", "Patty", "Ruth", "Vicki", "Annie", "Blossom", "Clara", "Eileen", "Mae", "Myra", "Rachel", "Tami", "Ashley", "Mikiko", "Kiana", "Perdy", "Maria", "Yuho", "Peren", "Barbara", "Diane" ]], + [TrainerType.BAKER]: [ "Chris", "Jenn", "Lilly" ], + [TrainerType.BEAUTY]: [ "Cassie", "Julia", "Olivia", "Samantha", "Valerie", "Victoria", "Bridget", "Connie", "Jessica", "Johanna", "Melissa", "Sheila", "Shirley", "Tiffany", "Namiko", "Thalia", "Grace", "Lola", "Lori", "Maura", "Tamia", "Cyndy", "Devon", "Gabriella", "Harley", "Lindsay", "Nicola", "Callie", "Charlotte", "Kassandra", "December", "Fleming", "Nikola", "Aimee", "Anais", "Brigitte", "Cassandra", "Andrea", "Brittney", "Carolyn", "Krystal", "Alexis", "Alice", "Aina", "Anya", "Arianna", "Aubrey", "Beverly", "Camille", "Beauty", "Evette", "Hansol", "Haruka", "Jill", "Jo", "Lana", "Lois", "Lucy", "Mai", "Nickie", "Nicole", "Prita", "Rose", "Shelly", "Suzy", "Tessa", "Anita", "Alissa", "Rita", "Cudsy", "Eloff", "Miru", "Minot", "Nevah", "Niven", "Ogoin" ], + [TrainerType.BIKER]: [ "Charles", "Dwayne", "Glenn", "Harris", "Joel", "Riley", "Zeke", "Alex", "Billy", "Ernest", "Gerald", "Hideo", "Isaac", "Jared", "Jaren", "Jaxon", "Jordy", "Lao", "Lukas", "Malik", "Nikolas", "Ricardo", "Ruben", "Virgil", "William", "Aiden", "Dale", "Dan", "Jacob", "Markey", "Reese", "Teddy", "Theron", "Jeremy", "Morgann", "Phillip", "Philip", "Stanley", "Dillon" ], + [TrainerType.BLACK_BELT]: [[ "Kenji", "Lao", "Lung", "Nob", "Wai", "Yoshi", "Atsushi", "Daisuke", "Hideki", "Hitoshi", "Kiyo", "Koichi", "Koji", "Yuji", "Cristian", "Rhett", "Takao", "Theodore", "Zander", "Aaron", "Hugh", "Mike", "Nicolas", "Shea", "Takashi", "Adam", "Carl", "Colby", "Darren", "David", "Davon", "Derek", "Eddie", "Gregory", "Griffin", "Jarrett", "Jeffery", "Kendal", "Kyle", "Luke", "Miles", "Nathaniel", "Philip", "Rafael", "Ray", "Ricky", "Sean", "Willie", "Ander", "Manford", "Benjamin", "Corey", "Edward", "Grant", "Jay", "Kendrew", "Kentaro", "Ryder", "Teppei", "Thomas", "Tyrone", "Andrey", "Donny", "Drago", "Gordon", "Grigor", "Jeriel", "Kenneth", "Martell", "Mathis", "Rich", "Rocky", "Rodrigo", "Wesley", "Zachery", "Alonzo", "Cadoc", "Gunnar", "Igor", "Killian", "Markus", "Ricardo", "Yanis", "Banting", "Clayton", "Duane", "Earl", "Greg", "Roy", "Terry", "Tracy", "Walter", "Alvaro", "Curtis", "Francis", "Ross", "Brice", "Cheng", "Dudley", "Eric", "Kano", "Masahiro", "Randy", "Ryuji", "Steve", "Tadashi", "Wong", "Yuen", "Brian", "Carter", "Reece", "Nick", "Yang" ], [ "Cora", "Cyndy", "Jill", "Laura", "Sadie", "Tessa", "Vivian", "Aisha", "Callie", "Danielle", "Helene", "Jocelyn", "Lilith", "Paula", "Reyna", "Helen", "Kelsey", "Tyler", "Amy", "Chandra", "Hillary", "Janie", "Lee", "Maggie", "Mikiko", "Miriam", "Sharon", "Susie", "Xiao", "Alize", "Azra", "Brenda", "Chalina", "Chan", "Glinda", "Maki", "Tia", "Tiffany", "Wendy", "Andrea", "Gabrielle", "Gerardine", "Hailey", "Hedvig", "Justine", "Kinsey", "Sigrid", "Veronique", "Tess" ]], + [TrainerType.BREEDER]: [[ "Isaac", "Myles", "Salvadore", "Albert", "Kahlil", "Eustace", "Galen", "Owen", "Addison", "Marcus", "Foster", "Cory", "Glenn", "Jay", "Wesley", "William", "Adrian", "Bradley", "Jaime" ], [ "Allison", "Alize", "Bethany", "Lily", "Lydia", "Gabrielle", "Jayden", "Pat", "Veronica", "Amber", "Jennifer", "Kaylee", "Adelaide", "Brooke", "Ethel", "April", "Irene", "Magnolia", "Amala", "Mercy", "Amanda", "Ikue", "Savannah", "Yuka", "Chloe", "Debra", "Denise", "Elena" ]], + [TrainerType.CLERK]: [[ "Chaz", "Clemens", "Doug", "Fredric", "Ivan", "Isaac", "Nelson", "Wade", "Warren", "Augustin", "Gilligan", "Cody", "Jeremy", "Shane", "Dugal", "Royce", "Ronald" ], [ "Alberta", "Ingrid", "Katie", "Piper", "Trisha", "Wren", "Britney", "Lana", "Jessica", "Kristen", "Michelle", "Gabrielle" ]], + [TrainerType.CYCLIST]: [[ "Axel", "James", "John", "Ryan", "Hector", "Jeremiah" ], [ "Kayla", "Megan", "Nicole", "Rachel", "Krissa", "Adelaide" ]], + [TrainerType.DANCER]: [ "Brian", "Davey", "Dirk", "Edmond", "Mickey", "Raymond", "Cara", "Julia", "Maika", "Mireille", "Ronda", "Zoe" ], + [TrainerType.DEPOT_AGENT]: [ "Josh", "Hank", "Vincent" ], + [TrainerType.DOCTOR]: [[ "Hank", "Jerry", "Jules", "Logan", "Wayne", "Braid", "Derek", "Heath", "Julius", "Kit", "Graham" ], [ "Kirsten", "Sachiko", "Shery", "Carol", "Dixie", "Mariah" ]], + [TrainerType.FIREBREATHER]: [ "Bill", "Burt", "Cliff", "Dick", "Lyle", "Ned", "Otis", "Ray", "Richard", "Walt" ], + [TrainerType.FISHERMAN]: [ "Andre", "Arnold", "Barney", "Chris", "Edgar", "Henry", "Jonah", "Justin", "Kyle", "Martin", "Marvin", "Ralph", "Raymond", "Scott", "Stephen", "Wilton", "Tully", "Andrew", "Barny", "Carter", "Claude", "Dale", "Elliot", "Eugene", "Ivan", "Ned", "Nolan", "Roger", "Ronald", "Wade", "Wayne", "Darian", "Kai", "Chip", "Hank", "Kaden", "Tommy", "Tylor", "Alec", "Brett", "Cameron", "Cody", "Cole", "Cory", "Erick", "George", "Joseph", "Juan", "Kenneth", "Luc", "Miguel", "Travis", "Walter", "Zachary", "Josh", "Gideon", "Kyler", "Liam", "Murphy", "Bruce", "Damon", "Devon", "Hubert", "Jones", "Lydon", "Mick", "Pete", "Sean", "Sid", "Vince", "Bucky", "Dean", "Eustace", "Kenzo", "Leroy", "Mack", "Ryder", "Ewan", "Finn", "Murray", "Seward", "Shad", "Wharton", "Finley", "Fisher", "Fisk", "River", "Sheaffer", "Timin", "Carl", "Ernest", "Hal", "Herbert", "Hisato", "Mike", "Vernon", "Harriet", "Marina", "Chase" ], + [TrainerType.GUITARIST]: [ "Anna", "Beverly", "January", "Tina", "Alicia", "Claudia", "Julia", "Lidia", "Mireia", "Noelia", "Sara", "Sheila", "Tatiana" ], + [TrainerType.HARLEQUIN]: [ "Charley", "Ian", "Jack", "Kerry", "Louis", "Pat", "Paul", "Rick", "Anders", "Clarence", "Gary" ], + [TrainerType.HIKER]: [ "Anthony", "Bailey", "Benjamin", "Daniel", "Erik", "Jim", "Kenny", "Leonard", "Michael", "Parry", "Phillip", "Russell", "Sidney", "Tim", "Timothy", "Alan", "Brice", "Clark", "Eric", "Lenny", "Lucas", "Mike", "Trent", "Devan", "Eli", "Marc", "Sawyer", "Allen", "Daryl", "Dudley", "Earl", "Franklin", "Jeremy", "Marcos", "Nob", "Oliver", "Wayne", "Alexander", "Damon", "Jonathan", "Justin", "Kevin", "Lorenzo", "Louis", "Maurice", "Nicholas", "Reginald", "Robert", "Theodore", "Bruce", "Clarke", "Devin", "Dwight", "Edwin", "Eoin", "Noland", "Russel", "Andy", "Bret", "Darrell", "Gene", "Hardy", "Hugh", "Jebediah", "Jeremiah", "Kit", "Neil", "Terrell", "Don", "Doug", "Hunter", "Jared", "Jerome", "Keith", "Manuel", "Markus", "Otto", "Shelby", "Stephen", "Teppei", "Tobias", "Wade", "Zaiem", "Aaron", "Alain", "Bergin", "Bernard", "Brent", "Corwin", "Craig", "Delmon", "Dunstan", "Orestes", "Ross", "Davian", "Calhoun", "David", "Gabriel", "Ryan", "Thomas", "Travis", "Zachary", "Anuhea", "Barnaby", "Claus", "Collin", "Colson", "Dexter", "Dillan", "Eugine", "Farkas", "Hisato", "Julius", "Kenji", "Irwin", "Lionel", "Paul", "Richter", "Valentino", "Donald", "Douglas", "Kevyn", "Chester" ], //["Angela","Carla","Celia","Daniela","Estela","Fatima","Helena","Leire","Lucia","Luna","Manuela","Mar","Marina","Miyu","Nancy","Nerea","Paula","Rocio","Yanira"] + [TrainerType.HOOLIGANS]: [ "Jim & Cas", "Rob & Sal" ], + [TrainerType.HOOPSTER]: [ "Bobby", "John", "Lamarcus", "Derrick", "Nicolas" ], + [TrainerType.INFIELDER]: [ "Alex", "Connor", "Todd" ], + [TrainerType.JANITOR]: [ "Caleb", "Geoff", "Brady", "Felix", "Orville", "Melvin", "Shawn" ], + [TrainerType.LINEBACKER]: [ "Bob", "Dan", "Jonah" ], + [TrainerType.MAID]: [ "Belinda", "Sophie", "Emily", "Elena", "Clare", "Alica", "Tanya", "Tammy" ], + [TrainerType.MUSICIAN]: [ "Boris", "Preston", "Charles", "Clyde", "Vincent", "Dalton", "Kirk", "Shawn", "Fabian", "Fernando", "Joseph", "Marcos", "Arturo", "Jerry", "Lonnie", "Tony" ], + [TrainerType.NURSERY_AIDE]: [ "Autumn", "Briana", "Leah", "Miho", "Ethel", "Hollie", "Ilse", "June", "Kimya", "Rosalyn" ], + [TrainerType.OFFICER]: [ "Dirk", "Keith", "Alex", "Bobby", "Caleb", "Danny", "Dylan", "Thomas", "Daniel", "Jeff", "Braven", "Dell", "Neagle", "Haruki", "Mitchell", "Raymond" ], + [TrainerType.PARASOL_LADY]: [ "Angelica", "Clarissa", "Madeline", "Akari", "Annabell", "Kayley", "Rachel", "Alexa", "Sabrina", "April", "Gwyneth", "Laura", "Lumi", "Mariah", "Melita", "Nicole", "Tihana", "Ingrid", "Tyra" ], + [TrainerType.PILOT]: [ "Chase", "Leonard", "Ted", "Elron", "Ewing", "Flynn", "Winslow" ], + [TrainerType.POKEFAN]: [[ "Alex", "Allan", "Brandon", "Carter", "Colin", "Derek", "Jeremy", "Joshua", "Rex", "Robert", "Trevor", "William", "Colton", "Miguel", "Francisco", "Kaleb", "Leonard", "Boone", "Elliot", "Jude", "Norbert", "Corey", "Gabe", "Baxter" ], [ "Beverly", "Georgia", "Jaime", "Ruth", "Isabel", "Marissa", "Vanessa", "Annika", "Bethany", "Kimberly", "Meredith", "Rebekah", "Eleanor", "Darcy", "Lydia", "Sachiko", "Abigail", "Agnes", "Lydie", "Roisin", "Tara", "Carmen", "Janet" ]], + [TrainerType.PRESCHOOLER]: [[ "Billy", "Doyle", "Evan", "Homer", "Tully", "Albert", "Buster", "Greg", "Ike", "Jojo", "Tyrone", "Adrian", "Oliver", "Hayden", "Hunter", "Kaleb", "Liam", "Dylan" ], [ "Juliet", "Mia", "Sarah", "Wendy", "Winter", "Chrissy", "Eva", "Lin", "Samantha", "Ella", "Lily", "Natalie", "Ailey", "Hannah", "Malia", "Kindra", "Nancy" ]], + [TrainerType.PSYCHIC]: [[ "Fidel", "Franklin", "Gilbert", "Greg", "Herman", "Jared", "Mark", "Nathan", "Norman", "Phil", "Richard", "Rodney", "Cameron", "Edward", "Fritz", "Joshua", "Preston", "Virgil", "William", "Alvaro", "Blake", "Cedric", "Keenan", "Nicholas", "Dario", "Johan", "Lorenzo", "Tyron", "Bryce", "Corbin", "Deandre", "Elijah", "Kody", "Landon", "Maxwell", "Mitchell", "Sterling", "Eli", "Nelson", "Vernon", "Gaven", "Gerard", "Low", "Micki", "Perry", "Rudolf", "Tommy", "Al", "Nandor", "Tully", "Arthur", "Emanuel", "Franz", "Harry", "Paschal", "Robert", "Sayid", "Angelo", "Anton", "Arin", "Avery", "Danny", "Frasier", "Harrison", "Jaime", "Ross", "Rui", "Vlad", "Mason" ], [ "Alexis", "Hannah", "Jacki", "Jaclyn", "Kayla", "Maura", "Samantha", "Alix", "Brandi", "Edie", "Macey", "Mariella", "Marlene", "Laura", "Rodette", "Abigail", "Brittney", "Chelsey", "Daisy", "Desiree", "Kendra", "Lindsey", "Rachael", "Valencia", "Belle", "Cybil", "Doreen", "Dua", "Future", "Lin", "Madhu", "Alia", "Ena", "Joyce", "Lynette", "Olesia", "Sarah" ]], + [TrainerType.RANGER]: [[ "Carlos", "Jackson", "Sebastian", "Gav", "Lorenzo", "Logan", "Nicolas", "Trenton", "Deshawn", "Dwayne", "Jeffery", "Kyler", "Taylor", "Alain", "Claude", "Crofton", "Forrest", "Harry", "Jaden", "Keith", "Lewis", "Miguel", "Pedro", "Ralph", "Richard", "Bret", "Daryl", "Eddie", "Johan", "Leaf", "Louis", "Maxwell", "Parker", "Rick", "Steve", "Bjorn", "Chaise", "Dean", "Lee", "Maurice", "Nash", "Ralf", "Reed", "Shinobu", "Silas" ], [ "Catherine", "Jenna", "Sophia", "Merdith", "Nora", "Beth", "Chelsea", "Katelyn", "Madeline", "Allison", "Ashlee", "Felicia", "Krista", "Annie", "Audra", "Brenda", "Chloris", "Eliza", "Heidi", "Irene", "Mary", "Mylene", "Shanti", "Shelly", "Thalia", "Anja", "Briana", "Dianna", "Elaine", "Elle", "Hillary", "Katie", "Lena", "Lois", "Malory", "Melita", "Mikiko", "Naoko", "Serenity", "Ambre", "Brooke", "Clementine", "Melina", "Petra", "Twiggy" ]], + [TrainerType.RICH]: [[ "Alfred", "Edward", "Gregory", "Preston", "Thomas", "Tucker", "Walter", "Clifford", "Everett", "Micah", "Nate", "Pierre", "Terrance", "Arthur", "Brooks", "Emanuel", "Lamar", "Jeremy", "Leonardo", "Milton", "Frederic", "Renaud", "Robert", "Yan", "Daniel", "Sheldon", "Stonewall", "Gerald", "Ronald", "Smith", "Stanley", "Reginald", "Orson", "Wilco", "Caden", "Glenn" ], [ "Rebecca", "Reina", "Cassandra", "Emilia", "Grace", "Marian", "Elizabeth", "Kathleen", "Sayuri", "Caroline", "Judy" ]], + [TrainerType.RICH_KID]: [[ "Garret", "Winston", "Dawson", "Enrique", "Jason", "Roman", "Trey", "Liam", "Anthony", "Brad", "Cody", "Manuel", "Martin", "Pierce", "Rolan", "Keenan", "Filbert", "Antoin", "Cyus", "Diek", "Dugo", "Flitz", "Jurek", "Lond", "Perd", "Quint", "Basto", "Benit", "Brot", "Denc", "Guyit", "Marcon", "Perc", "Puros", "Roex", "Sainz", "Symin", "Tark", "Venak" ], [ "Anette", "Brianna", "Cindy", "Colleen", "Daphne", "Elizabeth", "Naomi", "Sarah", "Charlotte", "Gillian", "Jacki", "Lady", "Melissa", "Celeste", "Colette", "Elizandra", "Isabel", "Lynette", "Magnolia", "Sophie", "Lina", "Dulcie", "Auro", "Brin", "Caril", "Eloos", "Gwin", "Illa", "Kowly", "Rima", "Ristin", "Vesey", "Brena", "Deasy", "Denslon", "Kylet", "Nemi", "Rene", "Sanol", "Stouner", "Sturk", "Talmen", "Zoila" ]], + [TrainerType.ROUGHNECK]: [ "Camron", "Corey", "Gabriel", "Isaiah", "Jamal", "Koji", "Luke", "Paxton", "Raul", "Zeek", "Kirby", "Chance", "Dave", "Fletcher", "Johnny", "Reese", "Joey", "Ricky", "Silvester", "Martin" ], + [TrainerType.SAILOR]: [ "Alberto", "Bost", "Brennan", "Brenden", "Claude", "Cory", "Damian", "Dirk", "Duncan", "Dwayne", "Dylan", "Eddie", "Edmond", "Elijah", "Ernest", "Eugene", "Garrett", "Golos", "Gratin", "Grestly", "Harry", "Hols", "Hudson", "Huey", "Jebol", "Jeff", "Leonald", "Luther", "Kelvin", "Kenneth", "Kent", "Knook", "Marc", "Mifis", "Monar", "Morkor", "Ordes", "Oxlin", "Parker", "Paul", "Philip", "Roberto", "Samson", "Skyler", "Stanly", "Tebu", "Terrell", "Trevor", "Yasu", "Zachariah" ], + [TrainerType.SCIENTIST]: [[ "Jed", "Marc", "Mitch", "Rich", "Ross", "Beau", "Braydon", "Connor", "Ed", "Ivan", "Jerry", "Jose", "Joshua", "Parker", "Rodney", "Taylor", "Ted", "Travis", "Zackery", "Darrius", "Emilio", "Fredrick", "Shaun", "Stefano", "Travon", "Daniel", "Garett", "Gregg", "Linden", "Lowell", "Trenton", "Dudley", "Luke", "Markus", "Nathan", "Orville", "Randall", "Ron", "Ronald", "Simon", "Steve", "William", "Franklin", "Clarke", "Jacques", "Terrance", "Ernst", "Justus", "Ikaika", "Jayson", "Kyle", "Reid", "Tyrone", "Adam", "Albert", "Alphonse", "Cory", "Donnie", "Elton", "Francis", "Gordon", "Herbert", "Humphrey", "Jordan", "Julian", "Keaton", "Levi", "Melvin", "Murray", "West", "Craig", "Coren", "Dubik", "Kotan", "Lethco", "Mante", "Mort", "Myron", "Odlow", "Ribek", "Roeck", "Vogi", "Vonder", "Zogo", "Doimo", "Doton", "Durel", "Hildon", "Kukla", "Messa", "Nanot", "Platen", "Raburn", "Reman", "Acrod", "Coffy", "Elrok", "Foss", "Hardig", "Hombol", "Hospel", "Kaller", "Klots", "Krilok", "Limar", "Loket", "Mesak", "Morbit", "Newin", "Orill", "Tabor", "Tekot" ], [ "Blythe", "Chan", "Kathrine", "Marie", "Maria", "Naoko", "Samantha", "Satomi", "Shannon", "Athena", "Caroline", "Lumi", "Lumina", "Marissa", "Sonia" ]], + [TrainerType.SMASHER]: [ "Aspen", "Elena", "Mari", "Amy", "Lizzy" ], + [TrainerType.SNOW_WORKER]: [[ "Braden", "Brendon", "Colin", "Conrad", "Dillan", "Gary", "Gerardo", "Holden", "Jackson", "Mason", "Quentin", "Willy", "Noel", "Arnold", "Brady", "Brand", "Cairn", "Cliff", "Don", "Eddie", "Felix", "Filipe", "Glenn", "Gus", "Heath", "Matthew", "Patton", "Rich", "Rob", "Ryan", "Scott", "Shelby", "Sterling", "Tyler", "Victor", "Zack", "Friedrich", "Herman", "Isaac", "Leo", "Maynard", "Mitchell", "Morgann", "Nathan", "Niel", "Pasqual", "Paul", "Tavarius", "Tibor", "Dimitri", "Narek", "Yusif", "Frank", "Jeff", "Vaclav", "Ovid", "Francis", "Keith", "Russel", "Sangon", "Toway", "Bomber", "Chean", "Demit", "Hubor", "Kebile", "Laber", "Ordo", "Retay", "Ronix", "Wagel", "Dobit", "Kaster", "Lobel", "Releo", "Saken", "Rustix" ], [ "Georgia", "Sandra", "Yvonne" ]], + [TrainerType.STRIKER]: [ "Marco", "Roberto", "Tony" ], + [TrainerType.SCHOOL_KID]: [[ "Alan", "Billy", "Chad", "Danny", "Dudley", "Jack", "Joe", "Johnny", "Kipp", "Nate", "Ricky", "Tommy", "Jerry", "Paul", "Ted", "Chance", "Esteban", "Forrest", "Harrison", "Connor", "Sherman", "Torin", "Travis", "Al", "Carter", "Edgar", "Jem", "Sammy", "Shane", "Shayne", "Alvin", "Keston", "Neil", "Seymour", "William", "Carson", "Clark", "Nolan" ], [ "Georgia", "Karen", "Meiko", "Christine", "Mackenzie", "Tiera", "Ann", "Gina", "Lydia", "Marsha", "Millie", "Sally", "Serena", "Silvia", "Alberta", "Cassie", "Mara", "Rita", "Georgie", "Meena", "Nitzel" ]], + [TrainerType.SWIMMER]: [[ "Berke", "Cameron", "Charlie", "George", "Harold", "Jerome", "Kirk", "Mathew", "Parker", "Randall", "Seth", "Simon", "Tucker", "Austin", "Barry", "Chad", "Cody", "Darrin", "David", "Dean", "Douglas", "Franklin", "Gilbert", "Herman", "Jack", "Luis", "Matthew", "Reed", "Richard", "Rodney", "Roland", "Spencer", "Stan", "Tony", "Clarence", "Declan", "Dominik", "Harrison", "Kevin", "Leonardo", "Nolen", "Pete", "Santiago", "Axle", "Braden", "Finn", "Garrett", "Mymo", "Reece", "Samir", "Toby", "Adrian", "Colton", "Dillon", "Erik", "Evan", "Francisco", "Glenn", "Kurt", "Oscar", "Ricardo", "Sam", "Sheltin", "Troy", "Vincent", "Wade", "Wesley", "Duane", "Elmo", "Esteban", "Frankie", "Ronald", "Tyson", "Bart", "Matt", "Tim", "Wright", "Jeffery", "Kyle", "Alessandro", "Estaban", "Kieran", "Ramses", "Casey", "Dakota", "Jared", "Kalani", "Keoni", "Lawrence", "Logan", "Robert", "Roddy", "Yasu", "Derek", "Jacob", "Bruce", "Clayton" ], [ "Briana", "Dawn", "Denise", "Diana", "Elaine", "Kara", "Kaylee", "Lori", "Nicole", "Nikki", "Paula", "Susie", "Wendy", "Alice", "Beth", "Beverly", "Brenda", "Dana", "Debra", "Grace", "Jenny", "Katie", "Laurel", "Linda", "Missy", "Sharon", "Tanya", "Tara", "Tisha", "Carlee", "Imani", "Isabelle", "Kyla", "Sienna", "Abigail", "Amara", "Anya", "Connie", "Maria", "Melissa", "Nora", "Shirley", "Shania", "Tiffany", "Aubree", "Cassandra", "Claire", "Crystal", "Erica", "Gabrielle", "Haley", "Jessica", "Joanna", "Lydia", "Mallory", "Mary", "Miranda", "Paige", "Sophia", "Vanessa", "Chelan", "Debbie", "Joy", "Kendra", "Leona", "Mina", "Caroline", "Joyce", "Larissa", "Rebecca", "Tyra", "Dara", "Desiree", "Kaoru", "Ruth", "Coral", "Genevieve", "Isla", "Marissa", "Romy", "Sheryl", "Alexandria", "Alicia", "Chelsea", "Jade", "Kelsie", "Laura", "Portia", "Shelby", "Sara", "Tiare", "Kyra", "Natasha", "Layla", "Scarlett", "Cora" ]], + [TrainerType.TWINS]: [ "Amy & May", "Jo & Zoe", "Meg & Peg", "Ann & Anne", "Lea & Pia", "Amy & Liv", "Gina & Mia", "Miu & Yuki", "Tori & Tia", "Eli & Anne", "Jen & Kira", "Joy & Meg", "Kiri & Jan", "Miu & Mia", "Emma & Lil", "Liv & Liz", "Teri & Tia", "Amy & Mimi", "Clea & Gil", "Day & Dani", "Kay & Tia", "Tori & Til", "Saya & Aya", "Emy & Lin", "Kumi & Amy", "Mayo & May", "Ally & Amy", "Lia & Lily", "Rae & Ula", "Sola & Ana", "Tara & Val", "Faith & Joy", "Nana & Nina" ], + [TrainerType.VETERAN]: [[ "Armando", "Brenden", "Brian", "Clayton", "Edgar", "Emanuel", "Grant", "Harlan", "Terrell", "Arlen", "Chester", "Hugo", "Martell", "Ray", "Shaun", "Abraham", "Carter", "Claude", "Jerry", "Lucius", "Murphy", "Rayne", "Ron", "Sinan", "Sterling", "Vincent", "Zach", "Gerard", "Gilles", "Louis", "Timeo", "Akira", "Don", "Eric", "Harry", "Leon", "Roger", "Angus", "Aristo", "Brone", "Johnny" ], [ "Julia", "Karla", "Kim", "Sayuri", "Tiffany", "Cathy", "Cecile", "Chloris", "Denae", "Gina", "Maya", "Oriana", "Portia", "Rhona", "Rosaline", "Catrina", "Inga", "Trisha", "Heather", "Lynn", "Sheri", "Alonsa", "Ella", "Leticia", "Kiara" ]], + [TrainerType.WAITER]: [[ "Bert", "Clint", "Maxwell", "Lou" ], [ "Kati", "Aurora", "Bonita", "Flo", "Tia", "Jan", "Olwen", "Paget", "Paula", "Talia" ]], + [TrainerType.WORKER]: [[ "Braden", "Brendon", "Colin", "Conrad", "Dillan", "Gary", "Gerardo", "Holden", "Jackson", "Mason", "Quentin", "Willy", "Noel", "Arnold", "Brady", "Brand", "Cairn", "Cliff", "Don", "Eddie", "Felix", "Filipe", "Glenn", "Gus", "Heath", "Matthew", "Patton", "Rich", "Rob", "Ryan", "Scott", "Shelby", "Sterling", "Tyler", "Victor", "Zack", "Friedrich", "Herman", "Isaac", "Leo", "Maynard", "Mitchell", "Morgann", "Nathan", "Niel", "Pasqual", "Paul", "Tavarius", "Tibor", "Dimitri", "Narek", "Yusif", "Frank", "Jeff", "Vaclav", "Ovid", "Francis", "Keith", "Russel", "Sangon", "Toway", "Bomber", "Chean", "Demit", "Hubor", "Kebile", "Laber", "Ordo", "Retay", "Ronix", "Wagel", "Dobit", "Kaster", "Lobel", "Releo", "Saken", "Rustix" ], [ "Georgia", "Sandra", "Yvonne" ]], + [TrainerType.YOUNGSTER]: [[ "Albert", "Gordon", "Ian", "Jason", "Jimmy", "Mikey", "Owen", "Samuel", "Warren", "Allen", "Ben", "Billy", "Calvin", "Dillion", "Eddie", "Joey", "Josh", "Neal", "Timmy", "Tommy", "Breyden", "Deandre", "Demetrius", "Dillon", "Jaylen", "Johnson", "Shigenobu", "Chad", "Cole", "Cordell", "Dan", "Dave", "Destin", "Nash", "Tyler", "Yasu", "Austin", "Dallas", "Darius", "Donny", "Jonathon", "Logan", "Michael", "Oliver", "Sebastian", "Tristan", "Wayne", "Norman", "Roland", "Regis", "Abe", "Astor", "Keita", "Kenneth", "Kevin", "Kyle", "Lester", "Masao", "Nicholas", "Parker", "Wes", "Zachary", "Cody", "Henley", "Jaye", "Karl", "Kenny", "Masahiro", "Pedro", "Petey", "Sinclair", "Terrell", "Waylon", "Aidan", "Anthony", "David", "Jacob", "Jayden", "Cutler", "Ham", "Caleb", "Kai", "Honus", "Kenway", "Bret", "Chris", "Cid", "Dennis", "Easton", "Ken", "Robby", "Ronny", "Shawn", "Benjamin", "Jake", "Travis", "Adan", "Aday", "Beltran", "Elian", "Hernan", "Julen", "Luka", "Roi", "Bernie", "Dustin", "Jonathan", "Wyatt" ], [ "Alice", "Bridget", "Carrie", "Connie", "Dana", "Ellen", "Krise", "Laura", "Linda", "Michelle", "Shannon", "Andrea", "Crissy", "Janice", "Robin", "Sally", "Tiana", "Haley", "Ali", "Ann", "Dalia", "Dawn", "Iris", "Joana", "Julia", "Kay", "Lisa", "Megan", "Mikaela", "Miriam", "Paige", "Reli", "Blythe", "Briana", "Caroline", "Cassidy", "Kaitlin", "Madeline", "Molly", "Natalie", "Samantha", "Sarah", "Cathy", "Dye", "Eri", "Eva", "Fey", "Kara", "Lurleen", "Maki", "Mali", "Maya", "Miki", "Sibyl", "Daya", "Diana", "Flo", "Helia", "Henrietta", "Isabel", "Mai", "Persephone", "Serena", "Anna", "Charlotte", "Elin", "Elsa", "Lise", "Sara", "Suzette", "Audrey", "Emmy", "Isabella", "Madison", "Rika", "Rylee", "Salla", "Ellie", "Alexandra", "Amy", "Lass", "Brittany", "Chel", "Cindy", "Dianne", "Emily", "Emma", "Evelyn", "Hana", "Harleen", "Hazel", "Jocelyn", "Katrina", "Kimberly", "Lina", "Marge", "Mila", "Mizuki", "Rena", "Sal", "Satoko", "Summer", "Tomoe", "Vicky", "Yue", "Yumi", "Lauren", "Rei", "Riley", "Lois", "Nancy", "Tammy", "Terry" ]], + [TrainerType.HEX_MANIAC]: [ "Kindra", "Patricia", "Tammy", "Tasha", "Valerie", "Alaina", "Kathleen", "Leah", "Makie", "Sylvia", "Anina", "Arachna", "Carrie", "Desdemona", "Josette", "Luna", "Melanie", "Osanna", "Raziah" ], }; // function used in a commented code @@ -140,7 +140,7 @@ function fetchAndPopulateTrainerNames(url: string, parser: DOMParser, trainerNam if (!trainerListHeader) { return []; } - const elements = [...(trainerListHeader?.parentElement?.childNodes ?? [])]; + const elements = [ ...(trainerListHeader?.parentElement?.childNodes ?? []) ]; const startChildIndex = elements.indexOf(trainerListHeader); const endChildIndex = elements.findIndex(h => h.nodeName === "H2" && elements.indexOf(h) > startChildIndex); const tables = elements.filter(t => { @@ -152,7 +152,7 @@ function fetchAndPopulateTrainerNames(url: string, parser: DOMParser, trainerNam }).map(t => t as Element); console.log(url, tables); for (const table of tables) { - const trainerRows = [...table.querySelectorAll("tr:not(:first-child)")].filter(r => r.children.length === 9); + const trainerRows = [ ...table.querySelectorAll("tr:not(:first-child)") ].filter(r => r.children.length === 9); for (const row of trainerRows) { const nameCell = row.firstElementChild; if (!nameCell) { diff --git a/src/data/type.ts b/src/data/type.ts index 47bea8dd72b..483ec068d3c 100644 --- a/src/data/type.ts +++ b/src/data/type.ts @@ -29,260 +29,260 @@ export function getTypeDamageMultiplier(attackType: Type, defType: Type): TypeDa } switch (defType) { - case Type.NORMAL: - switch (attackType) { - case Type.FIGHTING: - return 2; - case Type.GHOST: - return 0; - default: - return 1; - } - case Type.FIGHTING: - switch (attackType) { - case Type.FLYING: - case Type.PSYCHIC: - case Type.FAIRY: - return 2; - case Type.ROCK: - case Type.BUG: - case Type.DARK: - return 0.5; - default: - return 1; - } - case Type.FLYING: - switch (attackType) { - case Type.ROCK: - case Type.ELECTRIC: - case Type.ICE: - return 2; - case Type.FIGHTING: - case Type.BUG: - case Type.GRASS: - return 0.5; - case Type.GROUND: - return 0; - default: - return 1; - } - case Type.POISON: - switch (attackType) { - case Type.GROUND: - case Type.PSYCHIC: - return 2; - case Type.FIGHTING: - case Type.POISON: - case Type.BUG: - case Type.GRASS: - case Type.FAIRY: - return 0.5; - default: - return 1; - } - case Type.GROUND: - switch (attackType) { - case Type.WATER: - case Type.GRASS: - case Type.ICE: - return 2; - case Type.POISON: - case Type.ROCK: - return 0.5; - case Type.ELECTRIC: - return 0; - default: - return 1; - } - case Type.ROCK: - switch (attackType) { - case Type.FIGHTING: - case Type.GROUND: - case Type.STEEL: - case Type.WATER: - case Type.GRASS: - return 2; case Type.NORMAL: - case Type.FLYING: - case Type.POISON: - case Type.FIRE: - return 0.5; - default: - return 1; - } - case Type.BUG: - switch (attackType) { - case Type.FLYING: - case Type.ROCK: - case Type.FIRE: - return 2; + switch (attackType) { + case Type.FIGHTING: + return 2; + case Type.GHOST: + return 0; + default: + return 1; + } case Type.FIGHTING: + switch (attackType) { + case Type.FLYING: + case Type.PSYCHIC: + case Type.FAIRY: + return 2; + case Type.ROCK: + case Type.BUG: + case Type.DARK: + return 0.5; + default: + return 1; + } + case Type.FLYING: + switch (attackType) { + case Type.ROCK: + case Type.ELECTRIC: + case Type.ICE: + return 2; + case Type.FIGHTING: + case Type.BUG: + case Type.GRASS: + return 0.5; + case Type.GROUND: + return 0; + default: + return 1; + } + case Type.POISON: + switch (attackType) { + case Type.GROUND: + case Type.PSYCHIC: + return 2; + case Type.FIGHTING: + case Type.POISON: + case Type.BUG: + case Type.GRASS: + case Type.FAIRY: + return 0.5; + default: + return 1; + } case Type.GROUND: - case Type.GRASS: - return 0.5; - default: - return 1; - } - case Type.GHOST: - switch (attackType) { + switch (attackType) { + case Type.WATER: + case Type.GRASS: + case Type.ICE: + return 2; + case Type.POISON: + case Type.ROCK: + return 0.5; + case Type.ELECTRIC: + return 0; + default: + return 1; + } + case Type.ROCK: + switch (attackType) { + case Type.FIGHTING: + case Type.GROUND: + case Type.STEEL: + case Type.WATER: + case Type.GRASS: + return 2; + case Type.NORMAL: + case Type.FLYING: + case Type.POISON: + case Type.FIRE: + return 0.5; + default: + return 1; + } + case Type.BUG: + switch (attackType) { + case Type.FLYING: + case Type.ROCK: + case Type.FIRE: + return 2; + case Type.FIGHTING: + case Type.GROUND: + case Type.GRASS: + return 0.5; + default: + return 1; + } case Type.GHOST: - case Type.DARK: - return 2; - case Type.POISON: - case Type.BUG: - return 0.5; - case Type.NORMAL: - case Type.FIGHTING: - return 0; - default: - return 1; - } - case Type.STEEL: - switch (attackType) { - case Type.FIGHTING: - case Type.GROUND: - case Type.FIRE: - return 2; - case Type.NORMAL: - case Type.FLYING: - case Type.ROCK: - case Type.BUG: + switch (attackType) { + case Type.GHOST: + case Type.DARK: + return 2; + case Type.POISON: + case Type.BUG: + return 0.5; + case Type.NORMAL: + case Type.FIGHTING: + return 0; + default: + return 1; + } case Type.STEEL: + switch (attackType) { + case Type.FIGHTING: + case Type.GROUND: + case Type.FIRE: + return 2; + case Type.NORMAL: + case Type.FLYING: + case Type.ROCK: + case Type.BUG: + case Type.STEEL: + case Type.GRASS: + case Type.PSYCHIC: + case Type.ICE: + case Type.DRAGON: + case Type.FAIRY: + return 0.5; + case Type.POISON: + return 0; + default: + return 1; + } + case Type.FIRE: + switch (attackType) { + case Type.GROUND: + case Type.ROCK: + case Type.WATER: + return 2; + case Type.BUG: + case Type.STEEL: + case Type.FIRE: + case Type.GRASS: + case Type.ICE: + case Type.FAIRY: + return 0.5; + default: + return 1; + } + case Type.WATER: + switch (attackType) { + case Type.GRASS: + case Type.ELECTRIC: + return 2; + case Type.STEEL: + case Type.FIRE: + case Type.WATER: + case Type.ICE: + return 0.5; + default: + return 1; + } case Type.GRASS: + switch (attackType) { + case Type.FLYING: + case Type.POISON: + case Type.BUG: + case Type.FIRE: + case Type.ICE: + return 2; + case Type.GROUND: + case Type.WATER: + case Type.GRASS: + case Type.ELECTRIC: + return 0.5; + default: + return 1; + } + case Type.ELECTRIC: + switch (attackType) { + case Type.GROUND: + return 2; + case Type.FLYING: + case Type.STEEL: + case Type.ELECTRIC: + return 0.5; + default: + return 1; + } case Type.PSYCHIC: + switch (attackType) { + case Type.BUG: + case Type.GHOST: + case Type.DARK: + return 2; + case Type.FIGHTING: + case Type.PSYCHIC: + return 0.5; + default: + return 1; + } case Type.ICE: + switch (attackType) { + case Type.FIGHTING: + case Type.ROCK: + case Type.STEEL: + case Type.FIRE: + return 2; + case Type.ICE: + return 0.5; + default: + return 1; + } case Type.DRAGON: - case Type.FAIRY: - return 0.5; - case Type.POISON: - return 0; - default: - return 1; - } - case Type.FIRE: - switch (attackType) { - case Type.GROUND: - case Type.ROCK: - case Type.WATER: - return 2; - case Type.BUG: - case Type.STEEL: - case Type.FIRE: - case Type.GRASS: - case Type.ICE: - case Type.FAIRY: - return 0.5; - default: - return 1; - } - case Type.WATER: - switch (attackType) { - case Type.GRASS: - case Type.ELECTRIC: - return 2; - case Type.STEEL: - case Type.FIRE: - case Type.WATER: - case Type.ICE: - return 0.5; - default: - return 1; - } - case Type.GRASS: - switch (attackType) { - case Type.FLYING: - case Type.POISON: - case Type.BUG: - case Type.FIRE: - case Type.ICE: - return 2; - case Type.GROUND: - case Type.WATER: - case Type.GRASS: - case Type.ELECTRIC: - return 0.5; - default: - return 1; - } - case Type.ELECTRIC: - switch (attackType) { - case Type.GROUND: - return 2; - case Type.FLYING: - case Type.STEEL: - case Type.ELECTRIC: - return 0.5; - default: - return 1; - } - case Type.PSYCHIC: - switch (attackType) { - case Type.BUG: - case Type.GHOST: + switch (attackType) { + case Type.ICE: + case Type.DRAGON: + case Type.FAIRY: + return 2; + case Type.FIRE: + case Type.WATER: + case Type.GRASS: + case Type.ELECTRIC: + return 0.5; + default: + return 1; + } case Type.DARK: - return 2; - case Type.FIGHTING: - case Type.PSYCHIC: - return 0.5; - default: - return 1; - } - case Type.ICE: - switch (attackType) { - case Type.FIGHTING: - case Type.ROCK: - case Type.STEEL: - case Type.FIRE: - return 2; - case Type.ICE: - return 0.5; - default: - return 1; - } - case Type.DRAGON: - switch (attackType) { - case Type.ICE: - case Type.DRAGON: + switch (attackType) { + case Type.FIGHTING: + case Type.BUG: + case Type.FAIRY: + return 2; + case Type.GHOST: + case Type.DARK: + return 0.5; + case Type.PSYCHIC: + return 0; + default: + return 1; + } case Type.FAIRY: - return 2; - case Type.FIRE: - case Type.WATER: - case Type.GRASS: - case Type.ELECTRIC: - return 0.5; - default: + switch (attackType) { + case Type.POISON: + case Type.STEEL: + return 2; + case Type.FIGHTING: + case Type.BUG: + case Type.DARK: + return 0.5; + case Type.DRAGON: + return 0; + default: + return 1; + } + case Type.STELLAR: return 1; - } - case Type.DARK: - switch (attackType) { - case Type.FIGHTING: - case Type.BUG: - case Type.FAIRY: - return 2; - case Type.GHOST: - case Type.DARK: - return 0.5; - case Type.PSYCHIC: - return 0; - default: - return 1; - } - case Type.FAIRY: - switch (attackType) { - case Type.POISON: - case Type.STEEL: - return 2; - case Type.FIGHTING: - case Type.BUG: - case Type.DARK: - return 0.5; - case Type.DRAGON: - return 0; - default: - return 1; - } - case Type.STELLAR: - return 1; } return 1; @@ -295,86 +295,86 @@ export function getTypeDamageMultiplier(attackType: Type, defType: Type): TypeDa export function getTypeDamageMultiplierColor(multiplier: TypeDamageMultiplier, side: "defense" | "offense"): string | undefined { if (side === "offense") { switch (multiplier) { - case 0: - return "#929292"; - case 0.125: - return "#FF5500"; - case 0.25: - return "#FF7400"; - case 0.5: - return "#FE8E00"; - case 1: - return undefined; - case 2: - return "#4AA500"; - case 4: - return "#4BB400"; - case 8: - return "#52C200"; + case 0: + return "#929292"; + case 0.125: + return "#FF5500"; + case 0.25: + return "#FF7400"; + case 0.5: + return "#FE8E00"; + case 1: + return undefined; + case 2: + return "#4AA500"; + case 4: + return "#4BB400"; + case 8: + return "#52C200"; } } else if (side === "defense") { switch (multiplier) { - case 0: - return "#B1B100"; - case 0.125: - return "#2DB4FF"; - case 0.25: - return "#00A4FF"; - case 0.5: - return "#0093FF"; - case 1: - return undefined; - case 2: - return "#FE8E00"; - case 4: - return "#FF7400"; - case 8: - return "#FF5500"; + case 0: + return "#B1B100"; + case 0.125: + return "#2DB4FF"; + case 0.25: + return "#00A4FF"; + case 0.5: + return "#0093FF"; + case 1: + return undefined; + case 2: + return "#FE8E00"; + case 4: + return "#FF7400"; + case 8: + return "#FF5500"; } } } export function getTypeRgb(type: Type): [ integer, integer, integer ] { switch (type) { - case Type.NORMAL: - return [ 168, 168, 120 ]; - case Type.FIGHTING: - return [ 192, 48, 40 ]; - case Type.FLYING: - return [ 168, 144, 240 ]; - case Type.POISON: - return [ 160, 64, 160 ]; - case Type.GROUND: - return [ 224, 192, 104 ]; - case Type.ROCK: - return [ 184, 160, 56 ]; - case Type.BUG: - return [ 168, 184, 32 ]; - case Type.GHOST: - return [ 112, 88, 152 ]; - case Type.STEEL: - return [ 184, 184, 208 ]; - case Type.FIRE: - return [ 240, 128, 48 ]; - case Type.WATER: - return [ 104, 144, 240 ]; - case Type.GRASS: - return [ 120, 200, 80 ]; - case Type.ELECTRIC: - return [ 248, 208, 48 ]; - case Type.PSYCHIC: - return [ 248, 88, 136 ]; - case Type.ICE: - return [ 152, 216, 216 ]; - case Type.DRAGON: - return [ 112, 56, 248 ]; - case Type.DARK: - return [ 112, 88, 72 ]; - case Type.FAIRY: - return [ 232, 136, 200 ]; - case Type.STELLAR: - return [ 255, 255, 255 ]; - default: - return [ 0, 0, 0 ]; + case Type.NORMAL: + return [ 168, 168, 120 ]; + case Type.FIGHTING: + return [ 192, 48, 40 ]; + case Type.FLYING: + return [ 168, 144, 240 ]; + case Type.POISON: + return [ 160, 64, 160 ]; + case Type.GROUND: + return [ 224, 192, 104 ]; + case Type.ROCK: + return [ 184, 160, 56 ]; + case Type.BUG: + return [ 168, 184, 32 ]; + case Type.GHOST: + return [ 112, 88, 152 ]; + case Type.STEEL: + return [ 184, 184, 208 ]; + case Type.FIRE: + return [ 240, 128, 48 ]; + case Type.WATER: + return [ 104, 144, 240 ]; + case Type.GRASS: + return [ 120, 200, 80 ]; + case Type.ELECTRIC: + return [ 248, 208, 48 ]; + case Type.PSYCHIC: + return [ 248, 88, 136 ]; + case Type.ICE: + return [ 152, 216, 216 ]; + case Type.DRAGON: + return [ 112, 56, 248 ]; + case Type.DARK: + return [ 112, 88, 72 ]; + case Type.FAIRY: + return [ 232, 136, 200 ]; + case Type.STELLAR: + return [ 255, 255, 255 ]; + default: + return [ 0, 0, 0 ]; } } diff --git a/src/data/variant.ts b/src/data/variant.ts index b7a01a4be89..13869635f1e 100644 --- a/src/data/variant.ts +++ b/src/data/variant.ts @@ -10,22 +10,22 @@ export const variantColorCache = {}; export function getVariantTint(variant: Variant): integer { switch (variant) { - case 0: - return 0xf8c020; - case 1: - return 0x20f8f0; - case 2: - return 0xe81048; + case 0: + return 0xf8c020; + case 1: + return 0x20f8f0; + case 2: + return 0xe81048; } } export function getVariantIcon(variant: Variant): integer { switch (variant) { - case 0: - return VariantTier.STANDARD; - case 1: - return VariantTier.RARE; - case 2: - return VariantTier.EPIC; + case 0: + return VariantTier.STANDARD; + case 1: + return VariantTier.RARE; + case 2: + return VariantTier.EPIC; } } diff --git a/src/data/weather.ts b/src/data/weather.ts index afdd0a958cf..20c03af77c8 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -33,10 +33,10 @@ export class Weather { isImmutable(): boolean { switch (this.weatherType) { - case WeatherType.HEAVY_RAIN: - case WeatherType.HARSH_SUN: - case WeatherType.STRONG_WINDS: - return true; + case WeatherType.HEAVY_RAIN: + case WeatherType.HARSH_SUN: + case WeatherType.STRONG_WINDS: + return true; } return false; @@ -44,9 +44,9 @@ export class Weather { isDamaging(): boolean { switch (this.weatherType) { - case WeatherType.SANDSTORM: - case WeatherType.HAIL: - return true; + case WeatherType.SANDSTORM: + case WeatherType.HAIL: + return true; } return false; @@ -54,10 +54,10 @@ export class Weather { isTypeDamageImmune(type: Type): boolean { switch (this.weatherType) { - case WeatherType.SANDSTORM: - return type === Type.GROUND || type === Type.ROCK || type === Type.STEEL; - case WeatherType.HAIL: - return type === Type.ICE; + case WeatherType.SANDSTORM: + return type === Type.GROUND || type === Type.ROCK || type === Type.STEEL; + case WeatherType.HAIL: + return type === Type.ICE; } return false; @@ -65,24 +65,24 @@ export class Weather { getAttackTypeMultiplier(attackType: Type): number { switch (this.weatherType) { - case WeatherType.SUNNY: - case WeatherType.HARSH_SUN: - if (attackType === Type.FIRE) { - return 1.5; - } - if (attackType === Type.WATER) { - return 0.5; - } - break; - case WeatherType.RAIN: - case WeatherType.HEAVY_RAIN: - if (attackType === Type.FIRE) { - return 0.5; - } - if (attackType === Type.WATER) { - return 1.5; - } - break; + case WeatherType.SUNNY: + case WeatherType.HARSH_SUN: + if (attackType === Type.FIRE) { + return 1.5; + } + if (attackType === Type.WATER) { + return 0.5; + } + break; + case WeatherType.RAIN: + case WeatherType.HEAVY_RAIN: + if (attackType === Type.FIRE) { + return 0.5; + } + if (attackType === Type.WATER) { + return 1.5; + } + break; } return 1; @@ -92,10 +92,10 @@ export class Weather { const moveType = user.getMoveType(move); switch (this.weatherType) { - case WeatherType.HARSH_SUN: - return move instanceof AttackMove && moveType === Type.WATER; - case WeatherType.HEAVY_RAIN: - return move instanceof AttackMove && moveType === Type.FIRE; + case WeatherType.HARSH_SUN: + return move instanceof AttackMove && moveType === Type.WATER; + case WeatherType.HEAVY_RAIN: + return move instanceof AttackMove && moveType === Type.FIRE; } return false; @@ -120,24 +120,24 @@ export class Weather { export function getWeatherStartMessage(weatherType: WeatherType): string | null { switch (weatherType) { - case WeatherType.SUNNY: - return i18next.t("weather:sunnyStartMessage"); - case WeatherType.RAIN: - return i18next.t("weather:rainStartMessage"); - case WeatherType.SANDSTORM: - return i18next.t("weather:sandstormStartMessage"); - case WeatherType.HAIL: - return i18next.t("weather:hailStartMessage"); - case WeatherType.SNOW: - return i18next.t("weather:snowStartMessage"); - case WeatherType.FOG: - return i18next.t("weather:fogStartMessage"); - case WeatherType.HEAVY_RAIN: - return i18next.t("weather:heavyRainStartMessage"); - case WeatherType.HARSH_SUN: - return i18next.t("weather:harshSunStartMessage"); - case WeatherType.STRONG_WINDS: - return i18next.t("weather:strongWindsStartMessage"); + case WeatherType.SUNNY: + return i18next.t("weather:sunnyStartMessage"); + case WeatherType.RAIN: + return i18next.t("weather:rainStartMessage"); + case WeatherType.SANDSTORM: + return i18next.t("weather:sandstormStartMessage"); + case WeatherType.HAIL: + return i18next.t("weather:hailStartMessage"); + case WeatherType.SNOW: + return i18next.t("weather:snowStartMessage"); + case WeatherType.FOG: + return i18next.t("weather:fogStartMessage"); + case WeatherType.HEAVY_RAIN: + return i18next.t("weather:heavyRainStartMessage"); + case WeatherType.HARSH_SUN: + return i18next.t("weather:harshSunStartMessage"); + case WeatherType.STRONG_WINDS: + return i18next.t("weather:strongWindsStartMessage"); } return null; @@ -145,24 +145,24 @@ export function getWeatherStartMessage(weatherType: WeatherType): string | null export function getWeatherLapseMessage(weatherType: WeatherType): string | null { switch (weatherType) { - case WeatherType.SUNNY: - return i18next.t("weather:sunnyLapseMessage"); - case WeatherType.RAIN: - return i18next.t("weather:rainLapseMessage"); - case WeatherType.SANDSTORM: - return i18next.t("weather:sandstormLapseMessage"); - case WeatherType.HAIL: - return i18next.t("weather:hailLapseMessage"); - case WeatherType.SNOW: - return i18next.t("weather:snowLapseMessage"); - case WeatherType.FOG: - return i18next.t("weather:fogLapseMessage"); - case WeatherType.HEAVY_RAIN: - return i18next.t("weather:heavyRainLapseMessage"); - case WeatherType.HARSH_SUN: - return i18next.t("weather:harshSunLapseMessage"); - case WeatherType.STRONG_WINDS: - return i18next.t("weather:strongWindsLapseMessage"); + case WeatherType.SUNNY: + return i18next.t("weather:sunnyLapseMessage"); + case WeatherType.RAIN: + return i18next.t("weather:rainLapseMessage"); + case WeatherType.SANDSTORM: + return i18next.t("weather:sandstormLapseMessage"); + case WeatherType.HAIL: + return i18next.t("weather:hailLapseMessage"); + case WeatherType.SNOW: + return i18next.t("weather:snowLapseMessage"); + case WeatherType.FOG: + return i18next.t("weather:fogLapseMessage"); + case WeatherType.HEAVY_RAIN: + return i18next.t("weather:heavyRainLapseMessage"); + case WeatherType.HARSH_SUN: + return i18next.t("weather:harshSunLapseMessage"); + case WeatherType.STRONG_WINDS: + return i18next.t("weather:strongWindsLapseMessage"); } return null; @@ -170,10 +170,10 @@ export function getWeatherLapseMessage(weatherType: WeatherType): string | null export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokemon): string | null { switch (weatherType) { - case WeatherType.SANDSTORM: - return i18next.t("weather:sandstormDamageMessage", {pokemonNameWithAffix: getPokemonNameWithAffix(pokemon)}); - case WeatherType.HAIL: - return i18next.t("weather:hailDamageMessage", {pokemonNameWithAffix: getPokemonNameWithAffix(pokemon)}); + case WeatherType.SANDSTORM: + return i18next.t("weather:sandstormDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }); + case WeatherType.HAIL: + return i18next.t("weather:hailDamageMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }); } return null; @@ -181,24 +181,24 @@ export function getWeatherDamageMessage(weatherType: WeatherType, pokemon: Pokem export function getWeatherClearMessage(weatherType: WeatherType): string | null { switch (weatherType) { - case WeatherType.SUNNY: - return i18next.t("weather:sunnyClearMessage"); - case WeatherType.RAIN: - return i18next.t("weather:rainClearMessage"); - case WeatherType.SANDSTORM: - return i18next.t("weather:sandstormClearMessage"); - case WeatherType.HAIL: - return i18next.t("weather:hailClearMessage"); - case WeatherType.SNOW: - return i18next.t("weather:snowClearMessage"); - case WeatherType.FOG: - return i18next.t("weather:fogClearMessage"); - case WeatherType.HEAVY_RAIN: - return i18next.t("weather:heavyRainClearMessage"); - case WeatherType.HARSH_SUN: - return i18next.t("weather:harshSunClearMessage"); - case WeatherType.STRONG_WINDS: - return i18next.t("weather:strongWindsClearMessage"); + case WeatherType.SUNNY: + return i18next.t("weather:sunnyClearMessage"); + case WeatherType.RAIN: + return i18next.t("weather:rainClearMessage"); + case WeatherType.SANDSTORM: + return i18next.t("weather:sandstormClearMessage"); + case WeatherType.HAIL: + return i18next.t("weather:hailClearMessage"); + case WeatherType.SNOW: + return i18next.t("weather:snowClearMessage"); + case WeatherType.FOG: + return i18next.t("weather:fogClearMessage"); + case WeatherType.HEAVY_RAIN: + return i18next.t("weather:heavyRainClearMessage"); + case WeatherType.HARSH_SUN: + return i18next.t("weather:harshSunClearMessage"); + case WeatherType.STRONG_WINDS: + return i18next.t("weather:strongWindsClearMessage"); } return null; @@ -206,41 +206,41 @@ export function getWeatherClearMessage(weatherType: WeatherType): string | null export function getTerrainStartMessage(terrainType: TerrainType): string | null { switch (terrainType) { - case TerrainType.MISTY: - return i18next.t("terrain:mistyStartMessage"); - case TerrainType.ELECTRIC: - return i18next.t("terrain:electricStartMessage"); - case TerrainType.GRASSY: - return i18next.t("terrain:grassyStartMessage"); - case TerrainType.PSYCHIC: - return i18next.t("terrain:psychicStartMessage"); - default: - console.warn("getTerrainStartMessage not defined. Using default null"); - return null; + case TerrainType.MISTY: + return i18next.t("terrain:mistyStartMessage"); + case TerrainType.ELECTRIC: + return i18next.t("terrain:electricStartMessage"); + case TerrainType.GRASSY: + return i18next.t("terrain:grassyStartMessage"); + case TerrainType.PSYCHIC: + return i18next.t("terrain:psychicStartMessage"); + default: + console.warn("getTerrainStartMessage not defined. Using default null"); + return null; } } export function getTerrainClearMessage(terrainType: TerrainType): string | null { switch (terrainType) { - case TerrainType.MISTY: - return i18next.t("terrain:mistyClearMessage"); - case TerrainType.ELECTRIC: - return i18next.t("terrain:electricClearMessage"); - case TerrainType.GRASSY: - return i18next.t("terrain:grassyClearMessage"); - case TerrainType.PSYCHIC: - return i18next.t("terrain:psychicClearMessage"); - default: - console.warn("getTerrainClearMessage not defined. Using default null"); - return null; + case TerrainType.MISTY: + return i18next.t("terrain:mistyClearMessage"); + case TerrainType.ELECTRIC: + return i18next.t("terrain:electricClearMessage"); + case TerrainType.GRASSY: + return i18next.t("terrain:grassyClearMessage"); + case TerrainType.PSYCHIC: + return i18next.t("terrain:psychicClearMessage"); + default: + console.warn("getTerrainClearMessage not defined. Using default null"); + return null; } } export function getTerrainBlockMessage(pokemon: Pokemon, terrainType: TerrainType): string { if (terrainType === TerrainType.MISTY) { - return i18next.t("terrain:mistyBlockMessage", {pokemonNameWithAffix: getPokemonNameWithAffix(pokemon)}); + return i18next.t("terrain:mistyBlockMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }); } - return i18next.t("terrain:defaultBlockMessage", {pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), terrainName: getTerrainName(terrainType)}); + return i18next.t("terrain:defaultBlockMessage", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), terrainName: getTerrainName(terrainType) }); } interface WeatherPoolEntry { @@ -252,126 +252,126 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a let weatherPool: WeatherPoolEntry[] = []; const hasSun = arena.getTimeOfDay() < 2; switch (arena.biomeType) { - case Biome.GRASS: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 7 } - ]; - if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 3 }); - } - break; - case Biome.TALL_GRASS: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 8 }, - { weatherType: WeatherType.RAIN, weight: 5 }, - ]; - if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 8 }); - } - break; - case Biome.FOREST: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 8 }, - { weatherType: WeatherType.RAIN, weight: 5 } - ]; - break; - case Biome.SEA: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 3 }, - { weatherType: WeatherType.RAIN, weight: 12 } - ]; - break; - case Biome.SWAMP: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 3 }, - { weatherType: WeatherType.RAIN, weight: 4 }, - { weatherType: WeatherType.FOG, weight: 1 } - ]; - break; - case Biome.BEACH: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 8 }, - { weatherType: WeatherType.RAIN, weight: 3 } - ]; - if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 }); - } - break; - case Biome.LAKE: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 10 }, - { weatherType: WeatherType.RAIN, weight: 5 }, - { weatherType: WeatherType.FOG, weight: 1 } - ]; - break; - case Biome.SEABED: - weatherPool = [ - { weatherType: WeatherType.RAIN, weight: 1 } - ]; - break; - case Biome.BADLANDS: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 8 }, - { weatherType: WeatherType.SANDSTORM, weight: 2 } - ]; - if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 }); - } - break; - case Biome.DESERT: - weatherPool = [ - { weatherType: WeatherType.SANDSTORM, weight: 2 } - ]; - if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); - } - break; - case Biome.ICE_CAVE: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 3 }, - { weatherType: WeatherType.SNOW, weight: 4 }, - { weatherType: WeatherType.HAIL, weight: 1 } - ]; - break; - case Biome.MEADOW: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 2 } - ]; - if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); - } - case Biome.VOLCANO: - weatherPool = [ - { weatherType: hasSun ? WeatherType.SUNNY : WeatherType.NONE, weight: 1 } - ]; - break; - case Biome.GRAVEYARD: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 3 }, - { weatherType: WeatherType.FOG, weight: 1 } - ]; - break; - case Biome.JUNGLE: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 8 }, - { weatherType: WeatherType.RAIN, weight: 2 } - ]; - break; - case Biome.SNOWY_FOREST: - weatherPool = [ - { weatherType: WeatherType.SNOW, weight: 7 }, - { weatherType: WeatherType.HAIL, weight: 1 } - ]; - break; - case Biome.ISLAND: - weatherPool = [ - { weatherType: WeatherType.NONE, weight: 5 }, - { weatherType: WeatherType.RAIN, weight: 1 }, - ]; - if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); - } - break; + case Biome.GRASS: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 7 } + ]; + if (hasSun) { + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 3 }); + } + break; + case Biome.TALL_GRASS: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 8 }, + { weatherType: WeatherType.RAIN, weight: 5 }, + ]; + if (hasSun) { + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 8 }); + } + break; + case Biome.FOREST: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 8 }, + { weatherType: WeatherType.RAIN, weight: 5 } + ]; + break; + case Biome.SEA: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 3 }, + { weatherType: WeatherType.RAIN, weight: 12 } + ]; + break; + case Biome.SWAMP: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 3 }, + { weatherType: WeatherType.RAIN, weight: 4 }, + { weatherType: WeatherType.FOG, weight: 1 } + ]; + break; + case Biome.BEACH: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 8 }, + { weatherType: WeatherType.RAIN, weight: 3 } + ]; + if (hasSun) { + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 }); + } + break; + case Biome.LAKE: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 10 }, + { weatherType: WeatherType.RAIN, weight: 5 }, + { weatherType: WeatherType.FOG, weight: 1 } + ]; + break; + case Biome.SEABED: + weatherPool = [ + { weatherType: WeatherType.RAIN, weight: 1 } + ]; + break; + case Biome.BADLANDS: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 8 }, + { weatherType: WeatherType.SANDSTORM, weight: 2 } + ]; + if (hasSun) { + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 }); + } + break; + case Biome.DESERT: + weatherPool = [ + { weatherType: WeatherType.SANDSTORM, weight: 2 } + ]; + if (hasSun) { + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); + } + break; + case Biome.ICE_CAVE: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 3 }, + { weatherType: WeatherType.SNOW, weight: 4 }, + { weatherType: WeatherType.HAIL, weight: 1 } + ]; + break; + case Biome.MEADOW: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 2 } + ]; + if (hasSun) { + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); + } + case Biome.VOLCANO: + weatherPool = [ + { weatherType: hasSun ? WeatherType.SUNNY : WeatherType.NONE, weight: 1 } + ]; + break; + case Biome.GRAVEYARD: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 3 }, + { weatherType: WeatherType.FOG, weight: 1 } + ]; + break; + case Biome.JUNGLE: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 8 }, + { weatherType: WeatherType.RAIN, weight: 2 } + ]; + break; + case Biome.SNOWY_FOREST: + weatherPool = [ + { weatherType: WeatherType.SNOW, weight: 7 }, + { weatherType: WeatherType.HAIL, weight: 1 } + ]; + break; + case Biome.ISLAND: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 5 }, + { weatherType: WeatherType.RAIN, weight: 1 }, + ]; + if (hasSun) { + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); + } + break; } if (weatherPool.length > 1) { diff --git a/src/enums/arena-tag-type.ts b/src/enums/arena-tag-type.ts index 123d70b64fa..c73f4ec2ae5 100644 --- a/src/enums/arena-tag-type.ts +++ b/src/enums/arena-tag-type.ts @@ -1,4 +1,3 @@ - export enum ArenaTagType { NONE = "NONE", MUD_SPORT = "MUD_SPORT", @@ -25,5 +24,8 @@ export enum ArenaTagType { SAFEGUARD = "SAFEGUARD", NO_CRIT = "NO_CRIT", IMPRISON = "IMPRISON", - PLASMA_FISTS = "PLASMA_FISTS", + ION_DELUGE = "ION_DELUGE", + FIRE_GRASS_PLEDGE = "FIRE_GRASS_PLEDGE", + WATER_FIRE_PLEDGE = "WATER_FIRE_PLEDGE", + GRASS_WATER_PLEDGE = "GRASS_WATER_PLEDGE", } diff --git a/src/enums/battler-tag-type.ts b/src/enums/battler-tag-type.ts index 209d36316f9..680dedb93cc 100644 --- a/src/enums/battler-tag-type.ts +++ b/src/enums/battler-tag-type.ts @@ -1,4 +1,3 @@ - export enum BattlerTagType { NONE = "NONE", RECHARGING = "RECHARGING", @@ -55,7 +54,7 @@ export enum BattlerTagType { CURSED = "CURSED", CHARGED = "CHARGED", ROOSTED = "ROOSTED", - MAGNET_RISEN = "MAGNET_RISEN", + FLOATING = "FLOATING", MINIMIZED = "MINIMIZED", DESTINY_BOND = "DESTINY_BOND", CENTER_OF_ATTENTION = "CENTER_OF_ATTENTION", @@ -81,9 +80,12 @@ export enum BattlerTagType { DOUBLE_SHOCKED = "DOUBLE_SHOCKED", AUTOTOMIZED = "AUTOTOMIZED", MYSTERY_ENCOUNTER_POST_SUMMON = "MYSTERY_ENCOUNTER_POST_SUMMON", + POWER_TRICK = "POWER_TRICK", HEAL_BLOCK = "HEAL_BLOCK", TORMENT = "TORMENT", TAUNT = "TAUNT", IMPRISON = "IMPRISON", SYRUP_BOMB = "SYRUP_BOMB", + ELECTRIFIED = "ELECTRIFIED", + TELEKINESIS = "TELEKINESIS" } diff --git a/src/enums/berry-type.ts b/src/enums/berry-type.ts index 8b7aab16010..97c69148146 100644 --- a/src/enums/berry-type.ts +++ b/src/enums/berry-type.ts @@ -1,4 +1,3 @@ - export enum BerryType { SITRUS, LUM, diff --git a/src/enums/biome.ts b/src/enums/biome.ts index 7088b2e99ac..bb9eaf454cc 100644 --- a/src/enums/biome.ts +++ b/src/enums/biome.ts @@ -1,4 +1,3 @@ - export enum Biome { TOWN, PLAINS, diff --git a/src/enums/egg-type.ts b/src/enums/egg-type.ts index d8d0facb020..901e60b3c76 100644 --- a/src/enums/egg-type.ts +++ b/src/enums/egg-type.ts @@ -1,6 +1,6 @@ export enum EggTier { COMMON, - GREAT, - ULTRA, - MASTER + RARE, + EPIC, + LEGENDARY } diff --git a/src/enums/stat.ts b/src/enums/stat.ts index a12d53e8559..6b3f7dc6d79 100644 --- a/src/enums/stat.ts +++ b/src/enums/stat.ts @@ -50,7 +50,7 @@ export function getStatStageChangeDescriptionKey(stages: number, isIncrease: boo return isIncrease ? "battle:statRose" : "battle:statFell"; } else if (stages === 2) { return isIncrease ? "battle:statSharplyRose" : "battle:statHarshlyFell"; - } else if (stages <= 6) { + } else if (stages > 2 && stages <= 6) { return isIncrease ? "battle:statRoseDrastically" : "battle:statSeverelyFell"; } return isIncrease ? "battle:statWontGoAnyHigher" : "battle:statWontGoAnyLower"; diff --git a/src/enums/time-of-day.ts b/src/enums/time-of-day.ts index 9363aa4c73a..3fd05308cc6 100644 --- a/src/enums/time-of-day.ts +++ b/src/enums/time-of-day.ts @@ -1,4 +1,3 @@ - export enum TimeOfDay { ALL = -1, DAWN, diff --git a/src/field/anims.ts b/src/field/anims.ts index 52a15aa4f20..c73c52027c5 100644 --- a/src/field/anims.ts +++ b/src/field/anims.ts @@ -4,21 +4,21 @@ import * as Utils from "../utils"; export function addPokeballOpenParticles(scene: BattleScene, x: number, y: number, pokeballType: PokeballType): void { switch (pokeballType) { - case PokeballType.POKEBALL: - doDefaultPbOpenParticles(scene, x, y, 48); - break; - case PokeballType.GREAT_BALL: - doDefaultPbOpenParticles(scene, x, y, 96); - break; - case PokeballType.ULTRA_BALL: - doUbOpenParticles(scene, x, y, 8); - break; - case PokeballType.ROGUE_BALL: - doUbOpenParticles(scene, x, y, 10); - break; - case PokeballType.MASTER_BALL: - doMbOpenParticles(scene, x, y); - break; + case PokeballType.POKEBALL: + doDefaultPbOpenParticles(scene, x, y, 48); + break; + case PokeballType.GREAT_BALL: + doDefaultPbOpenParticles(scene, x, y, 96); + break; + case PokeballType.ULTRA_BALL: + doUbOpenParticles(scene, x, y, 8); + break; + case PokeballType.ROGUE_BALL: + doUbOpenParticles(scene, x, y, 10); + break; + case PokeballType.MASTER_BALL: + doMbOpenParticles(scene, x, y); + break; } } diff --git a/src/field/arena.ts b/src/field/arena.ts index 9d5f1eb0a4e..7bfdf9a0000 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -129,18 +129,18 @@ export class Arena { if (ret.subLegendary || ret.legendary || ret.mythical) { switch (true) { - case (ret.baseTotal >= 720): - regen = level < 90; - break; - case (ret.baseTotal >= 670): - regen = level < 70; - break; - case (ret.baseTotal >= 580): - regen = level < 50; - break; - default: - regen = level < 30; - break; + case (ret.baseTotal >= 720): + regen = level < 90; + break; + case (ret.baseTotal >= 670): + regen = level < 70; + break; + case (ret.baseTotal >= 580): + regen = level < 50; + break; + default: + regen = level < 30; + break; } } } @@ -177,41 +177,41 @@ export class Arena { getSpeciesFormIndex(species: PokemonSpecies): integer { switch (species.speciesId) { - case Species.BURMY: - case Species.WORMADAM: - switch (this.biomeType) { - case Biome.BEACH: - return 1; - case Biome.SLUM: - return 2; - } - break; - case Species.ROTOM: - switch (this.biomeType) { - case Biome.VOLCANO: - return 1; - case Biome.SEA: - return 2; - case Biome.ICE_CAVE: - return 3; - case Biome.MOUNTAIN: - return 4; - case Biome.TALL_GRASS: - return 5; - } - break; - case Species.LYCANROC: - const timeOfDay = this.getTimeOfDay(); - switch (timeOfDay) { - case TimeOfDay.DAY: - case TimeOfDay.DAWN: - return 0; - case TimeOfDay.DUSK: - return 2; - case TimeOfDay.NIGHT: - return 1; - } - break; + case Species.BURMY: + case Species.WORMADAM: + switch (this.biomeType) { + case Biome.BEACH: + return 1; + case Biome.SLUM: + return 2; + } + break; + case Species.ROTOM: + switch (this.biomeType) { + case Biome.VOLCANO: + return 1; + case Biome.SEA: + return 2; + case Biome.ICE_CAVE: + return 3; + case Biome.MOUNTAIN: + return 4; + case Biome.TALL_GRASS: + return 5; + } + break; + case Species.LYCANROC: + const timeOfDay = this.getTimeOfDay(); + switch (timeOfDay) { + case TimeOfDay.DAY: + case TimeOfDay.DAWN: + return 0; + case TimeOfDay.DUSK: + return 2; + case TimeOfDay.NIGHT: + return 1; + } + break; } return 0; @@ -219,70 +219,70 @@ export class Arena { getTypeForBiome() { switch (this.biomeType) { - case Biome.TOWN: - case Biome.PLAINS: - case Biome.METROPOLIS: - return Type.NORMAL; - case Biome.GRASS: - case Biome.TALL_GRASS: - return Type.GRASS; - case Biome.FOREST: - case Biome.JUNGLE: - return Type.BUG; - case Biome.SLUM: - case Biome.SWAMP: - return Type.POISON; - case Biome.SEA: - case Biome.BEACH: - case Biome.LAKE: - case Biome.SEABED: - return Type.WATER; - case Biome.MOUNTAIN: - return Type.FLYING; - case Biome.BADLANDS: - return Type.GROUND; - case Biome.CAVE: - case Biome.DESERT: - return Type.ROCK; - case Biome.ICE_CAVE: - case Biome.SNOWY_FOREST: - return Type.ICE; - case Biome.MEADOW: - case Biome.FAIRY_CAVE: - case Biome.ISLAND: - return Type.FAIRY; - case Biome.POWER_PLANT: - return Type.ELECTRIC; - case Biome.VOLCANO: - return Type.FIRE; - case Biome.GRAVEYARD: - case Biome.TEMPLE: - return Type.GHOST; - case Biome.DOJO: - case Biome.CONSTRUCTION_SITE: - return Type.FIGHTING; - case Biome.FACTORY: - case Biome.LABORATORY: - return Type.STEEL; - case Biome.RUINS: - case Biome.SPACE: - return Type.PSYCHIC; - case Biome.WASTELAND: - case Biome.END: - return Type.DRAGON; - case Biome.ABYSS: - return Type.DARK; - default: - return Type.UNKNOWN; + case Biome.TOWN: + case Biome.PLAINS: + case Biome.METROPOLIS: + return Type.NORMAL; + case Biome.GRASS: + case Biome.TALL_GRASS: + return Type.GRASS; + case Biome.FOREST: + case Biome.JUNGLE: + return Type.BUG; + case Biome.SLUM: + case Biome.SWAMP: + return Type.POISON; + case Biome.SEA: + case Biome.BEACH: + case Biome.LAKE: + case Biome.SEABED: + return Type.WATER; + case Biome.MOUNTAIN: + return Type.FLYING; + case Biome.BADLANDS: + return Type.GROUND; + case Biome.CAVE: + case Biome.DESERT: + return Type.ROCK; + case Biome.ICE_CAVE: + case Biome.SNOWY_FOREST: + return Type.ICE; + case Biome.MEADOW: + case Biome.FAIRY_CAVE: + case Biome.ISLAND: + return Type.FAIRY; + case Biome.POWER_PLANT: + return Type.ELECTRIC; + case Biome.VOLCANO: + return Type.FIRE; + case Biome.GRAVEYARD: + case Biome.TEMPLE: + return Type.GHOST; + case Biome.DOJO: + case Biome.CONSTRUCTION_SITE: + return Type.FIGHTING; + case Biome.FACTORY: + case Biome.LABORATORY: + return Type.STEEL; + case Biome.RUINS: + case Biome.SPACE: + return Type.PSYCHIC; + case Biome.WASTELAND: + case Biome.END: + return Type.DRAGON; + case Biome.ABYSS: + return Type.DARK; + default: + return Type.UNKNOWN; } } getBgTerrainColorRatioForBiome(): number { switch (this.biomeType) { - case Biome.SPACE: - return 1; - case Biome.END: - return 0; + case Biome.SPACE: + return 1; + case Biome.END: + return 0; } return 131 / 180; @@ -392,16 +392,16 @@ export class Arena { return true; } - isMoveWeatherCancelled(user: Pokemon, move: Move) { - return this.weather && !this.weather.isEffectSuppressed(this.scene) && this.weather.isMoveWeatherCancelled(user, move); + public isMoveWeatherCancelled(user: Pokemon, move: Move): boolean { + return !!this.weather && !this.weather.isEffectSuppressed(this.scene) && this.weather.isMoveWeatherCancelled(user, move); } - isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move) { - return this.terrain && this.terrain.isMoveTerrainCancelled(user, targets, move); + public isMoveTerrainCancelled(user: Pokemon, targets: BattlerIndex[], move: Move): boolean { + return !!this.terrain && this.terrain.isMoveTerrainCancelled(user, targets, move); } - getTerrainType() : TerrainType { - return this.terrain?.terrainType || TerrainType.NONE; + public getTerrainType(): TerrainType { + return this.terrain?.terrainType ?? TerrainType.NONE; } getAttackTypeMultiplier(attackType: Type, grounded: boolean): number { @@ -424,52 +424,52 @@ export class Arena { */ getTrainerChance(): integer { switch (this.biomeType) { - case Biome.METROPOLIS: - return 2; - case Biome.SLUM: - case Biome.BEACH: - case Biome.DOJO: - case Biome.CONSTRUCTION_SITE: - return 4; - case Biome.PLAINS: - case Biome.GRASS: - case Biome.LAKE: - case Biome.CAVE: - return 6; - case Biome.TALL_GRASS: - case Biome.FOREST: - case Biome.SEA: - case Biome.SWAMP: - case Biome.MOUNTAIN: - case Biome.BADLANDS: - case Biome.DESERT: - case Biome.MEADOW: - case Biome.POWER_PLANT: - case Biome.GRAVEYARD: - case Biome.FACTORY: - case Biome.SNOWY_FOREST: - return 8; - case Biome.ICE_CAVE: - case Biome.VOLCANO: - case Biome.RUINS: - case Biome.WASTELAND: - case Biome.JUNGLE: - case Biome.FAIRY_CAVE: - return 12; - case Biome.SEABED: - case Biome.ABYSS: - case Biome.SPACE: - case Biome.TEMPLE: - return 16; - default: - return 0; + case Biome.METROPOLIS: + return 2; + case Biome.SLUM: + case Biome.BEACH: + case Biome.DOJO: + case Biome.CONSTRUCTION_SITE: + return 4; + case Biome.PLAINS: + case Biome.GRASS: + case Biome.LAKE: + case Biome.CAVE: + return 6; + case Biome.TALL_GRASS: + case Biome.FOREST: + case Biome.SEA: + case Biome.SWAMP: + case Biome.MOUNTAIN: + case Biome.BADLANDS: + case Biome.DESERT: + case Biome.MEADOW: + case Biome.POWER_PLANT: + case Biome.GRAVEYARD: + case Biome.FACTORY: + case Biome.SNOWY_FOREST: + return 8; + case Biome.ICE_CAVE: + case Biome.VOLCANO: + case Biome.RUINS: + case Biome.WASTELAND: + case Biome.JUNGLE: + case Biome.FAIRY_CAVE: + return 12; + case Biome.SEABED: + case Biome.ABYSS: + case Biome.SPACE: + case Biome.TEMPLE: + return 16; + default: + return 0; } } getTimeOfDay(): TimeOfDay { switch (this.biomeType) { - case Biome.ABYSS: - return TimeOfDay.NIGHT; + case Biome.ABYSS: + return TimeOfDay.NIGHT; } const waveCycle = ((this.scene.currentBattle?.waveIndex || 0) + this.scene.waveCycleOffset) % 40; @@ -491,35 +491,35 @@ export class Arena { isOutside(): boolean { switch (this.biomeType) { - case Biome.SEABED: - case Biome.CAVE: - case Biome.ICE_CAVE: - case Biome.POWER_PLANT: - case Biome.DOJO: - case Biome.FACTORY: - case Biome.ABYSS: - case Biome.FAIRY_CAVE: - case Biome.TEMPLE: - case Biome.LABORATORY: - return false; - default: - return true; + case Biome.SEABED: + case Biome.CAVE: + case Biome.ICE_CAVE: + case Biome.POWER_PLANT: + case Biome.DOJO: + case Biome.FACTORY: + case Biome.ABYSS: + case Biome.FAIRY_CAVE: + case Biome.TEMPLE: + case Biome.LABORATORY: + return false; + default: + return true; } } overrideTint(): [integer, integer, integer] { switch (Overrides.ARENA_TINT_OVERRIDE) { - case TimeOfDay.DUSK: - return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer]; - break; - case (TimeOfDay.NIGHT): - return [ 64, 64, 64 ]; - break; - case TimeOfDay.DAWN: - case TimeOfDay.DAY: - default: - return [ 128, 128, 128 ]; - break; + case TimeOfDay.DUSK: + return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer]; + break; + case (TimeOfDay.NIGHT): + return [ 64, 64, 64 ]; + break; + case TimeOfDay.DAWN: + case TimeOfDay.DAY: + default: + return [ 128, 128, 128 ]; + break; } } @@ -528,10 +528,10 @@ export class Arena { return this.overrideTint(); } switch (this.biomeType) { - case Biome.ABYSS: - return [ 64, 64, 64 ]; - default: - return [ 128, 128, 128 ]; + case Biome.ABYSS: + return [ 64, 64, 64 ]; + default: + return [ 128, 128, 128 ]; } } @@ -544,8 +544,8 @@ export class Arena { } switch (this.biomeType) { - default: - return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer]; + default: + return [ 98, 48, 73 ].map(c => Math.round((c + 128) / 2)) as [integer, integer, integer]; } } @@ -554,10 +554,10 @@ export class Arena { return this.overrideTint(); } switch (this.biomeType) { - case Biome.ABYSS: - case Biome.SPACE: - case Biome.END: - return this.getDayTint(); + case Biome.ABYSS: + case Biome.SPACE: + case Biome.END: + return this.getDayTint(); } if (!this.isOutside()) { @@ -565,8 +565,8 @@ export class Arena { } switch (this.biomeType) { - default: - return [ 48, 48, 98 ]; + default: + return [ 48, 48, 98 ]; } } @@ -579,26 +579,28 @@ export class Arena { * Applies each `ArenaTag` in this Arena, based on which side (self, enemy, or both) is passed in as a parameter * @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply * @param side {@linkcode ArenaTagSide} which side's arena tags to apply + * @param simulated if `true`, this applies arena tags without changing game state * @param args array of parameters that the called upon tags may need */ - applyTagsForSide(tagType: ArenaTagType | Constructor, side: ArenaTagSide, ...args: unknown[]): void { + applyTagsForSide(tagType: ArenaTagType | Constructor, side: ArenaTagSide, simulated: boolean, ...args: unknown[]): void { let tags = typeof tagType === "string" ? this.tags.filter(t => t.tagType === tagType) : this.tags.filter(t => t instanceof tagType); if (side !== ArenaTagSide.BOTH) { tags = tags.filter(t => t.side === side); } - tags.forEach(t => t.apply(this, args)); + tags.forEach(t => t.apply(this, simulated, ...args)); } /** * Applies the specified tag to both sides (ie: both user and trainer's tag that match the Tag specified) * by calling {@linkcode applyTagsForSide()} * @param tagType Either an {@linkcode ArenaTagType} string, or an actual {@linkcode ArenaTag} class to filter which ones to apply + * @param simulated if `true`, this applies arena tags without changing game state * @param args array of parameters that the called upon tags may need */ - applyTags(tagType: ArenaTagType | Constructor, ...args: unknown[]): void { - this.applyTagsForSide(tagType, ArenaTagSide.BOTH, ...args); + applyTags(tagType: ArenaTagType | Constructor, simulated: boolean, ...args: unknown[]): void { + this.applyTagsForSide(tagType, ArenaTagSide.BOTH, simulated, ...args); } /** @@ -745,77 +747,77 @@ export class Arena { getBgmLoopPoint(): number { switch (this.biomeType) { - case Biome.TOWN: - return 7.288; - case Biome.PLAINS: - return 17.485; - case Biome.GRASS: - return 1.995; - case Biome.TALL_GRASS: - return 9.608; - case Biome.METROPOLIS: - return 141.470; - case Biome.FOREST: - return 4.294; - case Biome.SEA: - return 0.024; - case Biome.SWAMP: - return 4.461; - case Biome.BEACH: - return 3.462; - case Biome.LAKE: - return 7.215; - case Biome.SEABED: - return 2.600; - case Biome.MOUNTAIN: - return 4.018; - case Biome.BADLANDS: - return 17.790; - case Biome.CAVE: - return 14.240; - case Biome.DESERT: - return 1.143; - case Biome.ICE_CAVE: - return 0.000; - case Biome.MEADOW: - return 3.891; - case Biome.POWER_PLANT: - return 9.447; - case Biome.VOLCANO: - return 17.637; - case Biome.GRAVEYARD: - return 3.232; - case Biome.DOJO: - return 6.205; - case Biome.FACTORY: - return 4.985; - case Biome.RUINS: - return 0.000; - case Biome.WASTELAND: - return 6.336; - case Biome.ABYSS: - return 5.130; - case Biome.SPACE: - return 20.036; - case Biome.CONSTRUCTION_SITE: - return 1.222; - case Biome.JUNGLE: - return 0.000; - case Biome.FAIRY_CAVE: - return 4.542; - case Biome.TEMPLE: - return 2.547; - case Biome.ISLAND: - return 2.751; - case Biome.LABORATORY: - return 114.862; - case Biome.SLUM: - return 0.000; - case Biome.SNOWY_FOREST: - return 3.047; - default: - console.warn(`missing bgm loop-point for biome "${Biome[this.biomeType]}" (=${this.biomeType})`); - return 0; + case Biome.TOWN: + return 7.288; + case Biome.PLAINS: + return 17.485; + case Biome.GRASS: + return 1.995; + case Biome.TALL_GRASS: + return 9.608; + case Biome.METROPOLIS: + return 141.470; + case Biome.FOREST: + return 4.294; + case Biome.SEA: + return 0.024; + case Biome.SWAMP: + return 4.461; + case Biome.BEACH: + return 3.462; + case Biome.LAKE: + return 7.215; + case Biome.SEABED: + return 2.600; + case Biome.MOUNTAIN: + return 4.018; + case Biome.BADLANDS: + return 17.790; + case Biome.CAVE: + return 14.240; + case Biome.DESERT: + return 1.143; + case Biome.ICE_CAVE: + return 0.000; + case Biome.MEADOW: + return 3.891; + case Biome.POWER_PLANT: + return 9.447; + case Biome.VOLCANO: + return 17.637; + case Biome.GRAVEYARD: + return 3.232; + case Biome.DOJO: + return 6.205; + case Biome.FACTORY: + return 4.985; + case Biome.RUINS: + return 0.000; + case Biome.WASTELAND: + return 6.336; + case Biome.ABYSS: + return 5.130; + case Biome.SPACE: + return 20.036; + case Biome.CONSTRUCTION_SITE: + return 1.222; + case Biome.JUNGLE: + return 0.000; + case Biome.FAIRY_CAVE: + return 4.542; + case Biome.TEMPLE: + return 2.547; + case Biome.ISLAND: + return 2.751; + case Biome.LABORATORY: + return 114.862; + case Biome.SLUM: + return 0.000; + case Biome.SNOWY_FOREST: + return 3.047; + default: + console.warn(`missing bgm loop-point for biome "${Biome[this.biomeType]}" (=${this.biomeType})`); + return 0; } } } @@ -826,32 +828,32 @@ export function getBiomeKey(biome: Biome): string { export function getBiomeHasProps(biomeType: Biome): boolean { switch (biomeType) { - case Biome.METROPOLIS: - case Biome.BEACH: - case Biome.LAKE: - case Biome.SEABED: - case Biome.MOUNTAIN: - case Biome.BADLANDS: - case Biome.CAVE: - case Biome.DESERT: - case Biome.ICE_CAVE: - case Biome.MEADOW: - case Biome.POWER_PLANT: - case Biome.VOLCANO: - case Biome.GRAVEYARD: - case Biome.FACTORY: - case Biome.RUINS: - case Biome.WASTELAND: - case Biome.ABYSS: - case Biome.CONSTRUCTION_SITE: - case Biome.JUNGLE: - case Biome.FAIRY_CAVE: - case Biome.TEMPLE: - case Biome.SNOWY_FOREST: - case Biome.ISLAND: - case Biome.LABORATORY: - case Biome.END: - return true; + case Biome.METROPOLIS: + case Biome.BEACH: + case Biome.LAKE: + case Biome.SEABED: + case Biome.MOUNTAIN: + case Biome.BADLANDS: + case Biome.CAVE: + case Biome.DESERT: + case Biome.ICE_CAVE: + case Biome.MEADOW: + case Biome.POWER_PLANT: + case Biome.VOLCANO: + case Biome.GRAVEYARD: + case Biome.FACTORY: + case Biome.RUINS: + case Biome.WASTELAND: + case Biome.ABYSS: + case Biome.CONSTRUCTION_SITE: + case Biome.JUNGLE: + case Biome.FAIRY_CAVE: + case Biome.TEMPLE: + case Biome.SNOWY_FOREST: + case Biome.ISLAND: + case Biome.LABORATORY: + case Biome.END: + return true; } return false; diff --git a/src/field/damage-number-handler.ts b/src/field/damage-number-handler.ts index ae0692da342..4ddcd2d3ee7 100644 --- a/src/field/damage-number-handler.ts +++ b/src/field/damage-number-handler.ts @@ -29,21 +29,21 @@ export default class DamageNumberHandler { let [ textColor, shadowColor ] : TextAndShadowArr = [ null, null ]; switch (result) { - case HitResult.SUPER_EFFECTIVE: - [ textColor, shadowColor ] = [ "#f8d030", "#b8a038" ]; - break; - case HitResult.NOT_VERY_EFFECTIVE: - [ textColor, shadowColor ] = [ "#f08030", "#c03028" ]; - break; - case HitResult.ONE_HIT_KO: - [ textColor, shadowColor ] = [ "#a040a0", "#483850" ]; - break; - case HitResult.HEAL: - [ textColor, shadowColor ] = [ "#78c850", "#588040" ]; - break; - default: - [ textColor, shadowColor ] = [ "#ffffff", "#636363" ]; - break; + case HitResult.SUPER_EFFECTIVE: + [ textColor, shadowColor ] = [ "#f8d030", "#b8a038" ]; + break; + case HitResult.NOT_VERY_EFFECTIVE: + [ textColor, shadowColor ] = [ "#f08030", "#c03028" ]; + break; + case HitResult.ONE_HIT_KO: + [ textColor, shadowColor ] = [ "#a040a0", "#483850" ]; + break; + case HitResult.HEAL: + [ textColor, shadowColor ] = [ "#78c850", "#588040" ]; + break; + default: + [ textColor, shadowColor ] = [ "#ffffff", "#636363" ]; + break; } if (textColor) { diff --git a/src/field/mystery-encounter-intro.ts b/src/field/mystery-encounter-intro.ts index 70588da5d44..12bcace500c 100644 --- a/src/field/mystery-encounter-intro.ts +++ b/src/field/mystery-encounter-intro.ts @@ -101,14 +101,14 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con const getSprite = (spriteKey: string, hasShadow?: boolean, yShadow?: number) => { const ret = this.scene.addFieldSprite(0, 0, spriteKey); ret.setOrigin(0.5, 1); - ret.setPipeline(this.scene.spritePipeline, { tone: [0.0, 0.0, 0.0, 0.0], hasShadow: !!hasShadow, yShadowOffset: yShadow ?? 0 }); + ret.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: !!hasShadow, yShadowOffset: yShadow ?? 0 }); return ret; }; const getItemSprite = (spriteKey: string, hasShadow?: boolean, yShadow?: number) => { const icon = this.scene.add.sprite(-19, 2, "items", spriteKey); icon.setOrigin(0.5, 1); - icon.setPipeline(this.scene.spritePipeline, { tone: [0.0, 0.0, 0.0, 0.0], hasShadow: !!hasShadow, yShadowOffset: yShadow ?? 0 }); + icon.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: !!hasShadow, yShadowOffset: yShadow ?? 0 }); return icon; }; diff --git a/src/field/pokemon-sprite-sparkle-handler.ts b/src/field/pokemon-sprite-sparkle-handler.ts index ccf6a098667..2c4c295eaa4 100644 --- a/src/field/pokemon-sprite-sparkle-handler.ts +++ b/src/field/pokemon-sprite-sparkle-handler.ts @@ -36,7 +36,7 @@ export default class PokemonSpriteSparkleHandler { const ratioY = s.height / height; const pixel = texture.manager.getPixel(pixelX, pixelY, texture.key, "__BASE"); if (pixel?.alpha) { - const [ xOffset, yOffset ] = [ -s.originX * s.width, -s.originY * s.height]; + const [ xOffset, yOffset ] = [ -s.originX * s.width, -s.originY * s.height ]; const sparkle = (s.scene as BattleScene).addFieldSprite(((pokemon?.x || 0) + s.x + pixelX * ratioX + xOffset), ((pokemon?.y || 0) + s.y + pixelY * ratioY + yOffset), "tera_sparkle"); sparkle.pipelineData["ignoreTimeTint"] = s.pipelineData["ignoreTimeTint"]; sparkle.setName("sprite-tera-sparkle"); diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index a3034f64f8c..c99c15cafd8 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -3,9 +3,9 @@ import BattleScene, { AnySound } from "#app/battle-scene"; import { Variant, VariantSet, variantColorCache } from "#app/data/variant"; import { variantData } from "#app/data/variant"; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "#app/ui/battle-info"; -import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget } from "#app/data/move"; +import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget, CombinedPledgeStabBoostAttr } from "#app/data/move"; import { default as PokemonSpecies, PokemonSpeciesForm, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; -import { getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters"; +import { CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER, getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters"; import { starterPassiveAbilities } from "#app/data/balance/passives"; import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils"; import * as Utils from "#app/utils"; @@ -19,7 +19,7 @@ import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims"; import { Status, StatusEffect, getRandomStatus } from "#app/data/status-effect"; import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions"; import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "#app/data/balance/tms"; -import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, SubstituteTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, MoveRestrictionBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag, TarShotTag, AutotomizedTag } from "../data/battler-tags"; +import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, SubstituteTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, MoveRestrictionBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag, TarShotTag, AutotomizedTag, PowerTrickTag } from "../data/battler-tags"; import { WeatherType } from "#app/data/weather"; import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "#app/data/arena-tag"; import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr, PostSetStatusAbAttr, applyPostSetStatusAbAttrs } from "#app/data/ability"; @@ -676,12 +676,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { getFieldPositionOffset(): [ number, number ] { switch (this.fieldPosition) { - case FieldPosition.CENTER: - return [ 0, 0 ]; - case FieldPosition.LEFT: - return [ -32, -8 ]; - case FieldPosition.RIGHT: - return [ 32, 0 ]; + case FieldPosition.CENTER: + return [ 0, 0 ]; + case FieldPosition.LEFT: + return [ -32, -8 ]; + case FieldPosition.RIGHT: + return [ 32, 0 ]; } } @@ -692,7 +692,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @see {@linkcode getFieldPositionOffset} */ getSubstituteOffset(): [ number, number ] { - return this.isPlayer() ? [-30, 10] : [30, -10]; + return this.isPlayer() ? [ -30, 10 ] : [ 30, -10 ]; } /** @@ -745,9 +745,16 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const relX = newOffset[0] - initialOffset[0]; const relY = newOffset[1] - initialOffset[1]; + const subTag = this.getTag(SubstituteTag); + if (duration) { + // TODO: can this use stricter typing? + const targets: any[] = [ this ]; + if (subTag?.sprite) { + targets.push(subTag.sprite); + } this.scene.tweens.add({ - targets: this, + targets: targets, x: (_target, _key, value: number) => value + relX, y: (_target, _key, value: number) => value + relY, duration: duration, @@ -757,6 +764,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } else { this.x += relX; this.y += relY; + if (subTag?.sprite) { + subTag.sprite.x += relX; + subTag.sprite.y += relY; + } } }); } @@ -902,37 +913,39 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { let ret = statValue.value * this.getStatStageMultiplier(stat, opponent, move, ignoreOppAbility, isCritical, simulated); switch (stat) { - case Stat.ATK: - if (this.getTag(BattlerTagType.SLOW_START)) { - ret >>= 1; - } - break; - case Stat.DEF: - if (this.isOfType(Type.ICE) && this.scene.arena.weather?.weatherType === WeatherType.SNOW) { - ret *= 1.5; - } - break; - case Stat.SPATK: - break; - case Stat.SPDEF: - if (this.isOfType(Type.ROCK) && this.scene.arena.weather?.weatherType === WeatherType.SANDSTORM) { - ret *= 1.5; - } - break; - case Stat.SPD: - // Check both the player and enemy to see if Tailwind should be multiplying the speed of the Pokemon - if ((this.isPlayer() && this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.PLAYER)) - || (!this.isPlayer() && this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, ArenaTagSide.ENEMY))) { - ret *= 2; - } + case Stat.ATK: + if (this.getTag(BattlerTagType.SLOW_START)) { + ret >>= 1; + } + break; + case Stat.DEF: + if (this.isOfType(Type.ICE) && this.scene.arena.weather?.weatherType === WeatherType.SNOW) { + ret *= 1.5; + } + break; + case Stat.SPATK: + break; + case Stat.SPDEF: + if (this.isOfType(Type.ROCK) && this.scene.arena.weather?.weatherType === WeatherType.SANDSTORM) { + ret *= 1.5; + } + break; + case Stat.SPD: + const side = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; + if (this.scene.arena.getTagOnSide(ArenaTagType.TAILWIND, side)) { + ret *= 2; + } + if (this.scene.arena.getTagOnSide(ArenaTagType.GRASS_WATER_PLEDGE, side)) { + ret >>= 2; + } - if (this.getTag(BattlerTagType.SLOW_START)) { - ret >>= 1; - } - if (this.status && this.status.effect === StatusEffect.PARALYSIS) { - ret >>= 1; - } - break; + if (this.getTag(BattlerTagType.SLOW_START)) { + ret >>= 1; + } + if (this.status && this.status.effect === StatusEffect.PARALYSIS) { + ret >>= 1; + } + break; } const highestStatBoost = this.findTag(t => t instanceof HighestStatBoostTag && (t as HighestStatBoostTag).stat === stat) as HighestStatBoostTag; @@ -977,7 +990,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { this.scene.applyModifier(PokemonIncrementingStatModifier, this.isPlayer(), this, s, statHolder); } - statHolder.value = Utils.clampInt(statHolder.value, 1, Number.MAX_SAFE_INTEGER); + statHolder.value = Phaser.Math.Clamp(statHolder.value, 1, Number.MAX_SAFE_INTEGER); this.setStat(s, statHolder.value); } @@ -1102,7 +1115,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Overrides moveset based on arrays specified in overrides.ts let overrideArray: Moves | Array = this.isPlayer() ? Overrides.MOVESET_OVERRIDE : Overrides.OPP_MOVESET_OVERRIDE; if (!Array.isArray(overrideArray)) { - overrideArray = [overrideArray]; + overrideArray = [ overrideArray ]; } if (overrideArray.length > 0) { if (!this.isPlayer()) { @@ -1388,10 +1401,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const suppressed = new Utils.BooleanHolder(false); this.scene.getField(true).filter(p => p !== this).map(p => { if (p.getAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility()) { - p.getAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, false, false, suppressed, [ability])); + p.getAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, false, false, suppressed, [ ability ])); } if (p.getPassiveAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility(true)) { - p.getPassiveAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, true, false, suppressed, [ability])); + p.getPassiveAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, true, false, suppressed, [ ability ])); } }); if (suppressed.value) { @@ -1411,10 +1424,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @returns {boolean} Whether the ability is present and active */ hasAbility(ability: Abilities, canApply: boolean = true, ignoreOverride?: boolean): boolean { - if ((!canApply || this.canApplyAbility()) && this.getAbility(ignoreOverride).id === ability) { + if (this.getAbility(ignoreOverride).id === ability && (!canApply || this.canApplyAbility())) { return true; } - if (this.hasPassive() && (!canApply || this.canApplyAbility(true)) && this.getPassiveAbility().id === ability) { + if (this.getPassiveAbility().id === ability && this.hasPassive() && (!canApply || this.canApplyAbility(true))) { return true; } return false; @@ -1482,7 +1495,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } isGrounded(): boolean { - return !!this.getTag(GroundedTag) || (!this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE) && !this.getTag(BattlerTagType.MAGNET_RISEN) && !this.getTag(SemiInvulnerableTag)); + return !!this.getTag(GroundedTag) || (!this.isOfType(Type.FLYING, true, true) && !this.hasAbility(Abilities.LEVITATE) && !this.getTag(BattlerTagType.FLOATING) && !this.getTag(SemiInvulnerableTag)); } /** @@ -1521,13 +1534,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder); applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder); - this.scene.arena.applyTags(ArenaTagType.PLASMA_FISTS, moveTypeHolder); + this.scene.arena.applyTags(ArenaTagType.ION_DELUGE, simulated, moveTypeHolder); + if (this.getTag(BattlerTagType.ELECTRIFIED)) { + moveTypeHolder.value = Type.ELECTRIC; + } return moveTypeHolder.value as Type; } - /** * Calculates the effectiveness of a move against the Pokémon. * This includes modifiers from move and ability attributes. @@ -1699,7 +1714,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (pokemonEvolutions.hasOwnProperty(this.species.speciesId)) { const evolutions = pokemonEvolutions[this.species.speciesId]; for (const e of evolutions) { - if (!e.item && this.level >= e.level && (!e.preFormKey || this.getFormKey() === e.preFormKey)) { + if (!e.item && this.level >= e.level && (isNullOrUndefined(e.preFormKey) || this.getFormKey() === e.preFormKey)) { if (e.condition === null || (e.condition as SpeciesEvolutionCondition).predicate(this)) { return e; } @@ -1710,7 +1725,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (this.isFusion() && this.fusionSpecies && pokemonEvolutions.hasOwnProperty(this.fusionSpecies.speciesId)) { const fusionEvolutions = pokemonEvolutions[this.fusionSpecies.speciesId].map(e => new FusionSpeciesFormEvolution(this.species.speciesId, e)); for (const fe of fusionEvolutions) { - if (!fe.item && this.level >= fe.level && (!fe.preFormKey || this.getFusionFormKey() === fe.preFormKey)) { + if (!fe.item && this.level >= fe.level && (isNullOrUndefined(fe.preFormKey) || this.getFusionFormKey() === fe.preFormKey)) { if (fe.condition === null || (fe.condition as SpeciesEvolutionCondition).predicate(this)) { return fe; } @@ -1961,7 +1976,15 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { && species.speciesId !== this.species.speciesId; }; - this.fusionSpecies = this.scene.randomSpecies(this.scene.currentBattle?.waveIndex || 0, this.level, false, filter, true); + let fusionOverride: PokemonSpecies | undefined = undefined; + + if (forStarter && this instanceof PlayerPokemon && Overrides.STARTER_FUSION_SPECIES_OVERRIDE) { + fusionOverride = getPokemonSpecies(Overrides.STARTER_FUSION_SPECIES_OVERRIDE); + } else if (this instanceof EnemyPokemon && Overrides.OPP_FUSION_SPECIES_OVERRIDE) { + fusionOverride = getPokemonSpecies(Overrides.OPP_FUSION_SPECIES_OVERRIDE); + } + + this.fusionSpecies = fusionOverride ?? this.scene.randomSpecies(this.scene.currentBattle?.waveIndex || 0, this.level, false, filter, true); this.fusionAbilityIndex = (this.fusionSpecies.abilityHidden && hasHiddenAbility ? 2 : this.fusionSpecies.ability2 !== this.fusionSpecies.ability1 ? randAbilityIndex : 0); this.fusionShiny = this.shiny; this.fusionVariant = this.variant; @@ -2022,7 +2045,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { weight /= 100; } // Unimplemented level up moves are possible to generate, but 1% of their normal chance. if (!movePool.some(m => m[0] === levelMove[1])) { - movePool.push([levelMove[1], weight]); + movePool.push([ levelMove[1], weight ]); } } @@ -2044,11 +2067,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } if (compatible && !movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(" (N)")) { if (tmPoolTiers[moveId] === ModifierTier.COMMON && this.level >= 15) { - movePool.push([moveId, 4]); + movePool.push([ moveId, 4 ]); } else if (tmPoolTiers[moveId] === ModifierTier.GREAT && this.level >= 30) { - movePool.push([moveId, 8]); + movePool.push([ moveId, 8 ]); } else if (tmPoolTiers[moveId] === ModifierTier.ULTRA && this.level >= 50) { - movePool.push([moveId, 14]); + movePool.push([ moveId, 14 ]); } } } @@ -2057,23 +2080,23 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { for (let i = 0; i < 3; i++) { const moveId = speciesEggMoves[this.species.getRootSpeciesId()][i]; if (!movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(" (N)")) { - movePool.push([moveId, 40]); + movePool.push([ moveId, 40 ]); } } const moveId = speciesEggMoves[this.species.getRootSpeciesId()][3]; if (this.level >= 170 && !movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(" (N)") && !this.isBoss()) { // No rare egg moves before e4 - movePool.push([moveId, 30]); + movePool.push([ moveId, 30 ]); } if (this.fusionSpecies) { for (let i = 0; i < 3; i++) { const moveId = speciesEggMoves[this.fusionSpecies.getRootSpeciesId()][i]; if (!movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(" (N)")) { - movePool.push([moveId, 40]); + movePool.push([ moveId, 40 ]); } } const moveId = speciesEggMoves[this.fusionSpecies.getRootSpeciesId()][3]; if (this.level >= 170 && !movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(" (N)") && !this.isBoss()) {// No rare egg moves before e4 - movePool.push([moveId, 30]); + movePool.push([ moveId, 30 ]); } } } @@ -2087,26 +2110,26 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Trainers never get OHKO moves movePool = movePool.filter(m => !allMoves[m[0]].hasAttr(OneHitKOAttr)); // Half the weight of self KO moves - movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(SacrificialAttr) ? 0.5 : 1)]); - movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(SacrificialAttrOnHit) ? 0.5 : 1)]); + movePool = movePool.map(m => [ m[0], m[1] * (!!allMoves[m[0]].hasAttr(SacrificialAttr) ? 0.5 : 1) ]); + movePool = movePool.map(m => [ m[0], m[1] * (!!allMoves[m[0]].hasAttr(SacrificialAttrOnHit) ? 0.5 : 1) ]); // Trainers get a weight bump to stat buffing moves - movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].getAttrs(StatStageChangeAttr).some(a => a.stages > 1 && a.selfTarget) ? 1.25 : 1)]); + movePool = movePool.map(m => [ m[0], m[1] * (allMoves[m[0]].getAttrs(StatStageChangeAttr).some(a => a.stages > 1 && a.selfTarget) ? 1.25 : 1) ]); // Trainers get a weight decrease to multiturn moves - movePool = movePool.map(m => [m[0], m[1] * (!!allMoves[m[0]].hasAttr(ChargeAttr) || !!allMoves[m[0]].hasAttr(RechargeAttr) ? 0.7 : 1)]); + movePool = movePool.map(m => [ m[0], m[1] * (!!allMoves[m[0]].hasAttr(ChargeAttr) || !!allMoves[m[0]].hasAttr(RechargeAttr) ? 0.7 : 1) ]); } // Weight towards higher power moves, by reducing the power of moves below the highest power. // Caps max power at 90 to avoid something like hyper beam ruining the stats. // This is a pretty soft weighting factor, although it is scaled with the weight multiplier. const maxPower = Math.min(movePool.reduce((v, m) => Math.max(allMoves[m[0]].power, v), 40), 90); - movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].category === MoveCategory.STATUS ? 1 : Math.max(Math.min(allMoves[m[0]].power/maxPower, 1), 0.5))]); + movePool = movePool.map(m => [ m[0], m[1] * (allMoves[m[0]].category === MoveCategory.STATUS ? 1 : Math.max(Math.min(allMoves[m[0]].power / maxPower, 1), 0.5)) ]); // Weight damaging moves against the lower stat const atk = this.getStat(Stat.ATK); const spAtk = this.getStat(Stat.SPATK); const worseCategory: MoveCategory = atk > spAtk ? MoveCategory.SPECIAL : MoveCategory.PHYSICAL; const statRatio = worseCategory === MoveCategory.PHYSICAL ? atk / spAtk : spAtk / atk; - movePool = movePool.map(m => [m[0], m[1] * (allMoves[m[0]].category === worseCategory ? statRatio : 1)]); + movePool = movePool.map(m => [ m[0], m[1] * (allMoves[m[0]].category === worseCategory ? statRatio : 1) ]); let weightMultiplier = 0.9; // The higher this is the more the game weights towards higher level moves. At 0 all moves are equal weight. if (this.hasTrainer()) { @@ -2115,7 +2138,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (this.isBoss()) { weightMultiplier += 0.4; } - const baseWeights: [Moves, number][] = movePool.map(m => [m[0], Math.ceil(Math.pow(m[1], weightMultiplier)*100)]); + const baseWeights: [Moves, number][] = movePool.map(m => [ m[0], Math.ceil(Math.pow(m[1], weightMultiplier) * 100) ]); if (this.hasTrainer() || this.isBoss()) { // Trainers and bosses always force a stab move const stabMovePool = baseWeights.filter(m => allMoves[m[0]].category !== MoveCategory.STATUS && this.isOfType(allMoves[m[0]].type)); @@ -2147,7 +2170,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // Sqrt the weight of any damaging moves with overlapping types. This is about a 0.05 - 0.1 multiplier. // Other damaging moves 2x weight if 0-1 damaging moves, 0.5x if 2, 0.125x if 3. These weights double if STAB. // Status moves remain unchanged on weight, this encourages 1-2 - movePool = baseWeights.filter(m => !this.moveset.some(mo => m[0] === mo?.moveId)).map(m => [m[0], this.moveset.some(mo => mo?.getMove().category !== MoveCategory.STATUS && mo?.getMove().type === allMoves[m[0]].type) ? Math.ceil(Math.sqrt(m[1])) : allMoves[m[0]].category !== MoveCategory.STATUS ? Math.ceil(m[1]/Math.max(Math.pow(4, this.moveset.filter(mo => (mo?.getMove().power!) > 1).length)/8, 0.5) * (this.isOfType(allMoves[m[0]].type) ? 2 : 1)) : m[1]]); // TODO: is this bang correct? + movePool = baseWeights.filter(m => !this.moveset.some(mo => m[0] === mo?.moveId)).map(m => [ m[0], this.moveset.some(mo => mo?.getMove().category !== MoveCategory.STATUS && mo?.getMove().type === allMoves[m[0]].type) ? Math.ceil(Math.sqrt(m[1])) : allMoves[m[0]].category !== MoveCategory.STATUS ? Math.ceil(m[1] / Math.max(Math.pow(4, this.moveset.filter(mo => (mo?.getMove().power!) > 1).length) / 8, 0.5) * (this.isOfType(allMoves[m[0]].type) ? 2 : 1)) : m[1] ]); // TODO: is this bang correct? } else { // Non-trainer pokemon just use normal weights movePool = baseWeights.filter(m => !this.moveset.some(mo => m[0] === mo?.moveId)); } @@ -2311,14 +2334,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (opponent) { if (isCritical) { switch (stat) { - case Stat.ATK: - case Stat.SPATK: - statStage.value = Math.max(statStage.value, 0); - break; - case Stat.DEF: - case Stat.SPDEF: - statStage.value = Math.min(statStage.value, 0); - break; + case Stat.ATK: + case Stat.SPATK: + statStage.value = Math.max(statStage.value, 0); + break; + case Stat.DEF: + case Stat.SPDEF: + statStage.value = Math.min(statStage.value, 0); + break; } } if (!ignoreOppAbility) { @@ -2551,6 +2574,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (matchesSourceType) { stabMultiplier.value += 0.5; } + applyMoveAttrs(CombinedPledgeStabBoostAttr, source, this, move, stabMultiplier); if (sourceTeraType !== Type.UNKNOWN && sourceTeraType === moveType) { stabMultiplier.value += 0.5; } @@ -2577,7 +2601,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { /** Reduces damage if this Pokemon has a relevant screen (e.g. Light Screen for special attacks) */ const screenMultiplier = new Utils.NumberHolder(1); - this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, defendingSide, move.category, this.scene.currentBattle.double, screenMultiplier); + this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, defendingSide, simulated, moveCategory, screenMultiplier); /** * For each {@linkcode HitsTagAttr} the move has, doubles the damage of the move if: @@ -2667,7 +2691,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { */ apply(source: Pokemon, move: Move): HitResult { const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; - if (move.category === MoveCategory.STATUS) { + const moveCategory = new Utils.NumberHolder(move.category); + applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, moveCategory); + if (moveCategory.value === MoveCategory.STATUS) { const cancelled = new Utils.BooleanHolder(false); const typeMultiplier = this.getMoveEffectiveness(source, move, false, false, cancelled); @@ -2685,7 +2711,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (critOnly.value || critAlways) { isCritical = true; } else { - const critChance = [24, 8, 2, 1][Math.max(0, Math.min(this.getCritStage(source, move), 3))]; + const critChance = [ 24, 8, 2, 1 ][Math.max(0, Math.min(this.getCritStage(source, move), 3))]; isCritical = critChance === 1 || !this.scene.randBattleSeedInt(critChance); } @@ -2741,7 +2767,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (damage > 0) { if (source.isPlayer()) { - this.scene.validateAchvs(DamageAchv, damage); + this.scene.validateAchvs(DamageAchv, new Utils.NumberHolder(damage)); if (damage > this.scene.gameData.gameStats.highestDamage) { this.scene.gameData.gameStats.highestDamage = damage; } @@ -2765,30 +2791,31 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { // want to include is.Fainted() in case multi hit move ends early, still want to render message if (source.turnData.hitsLeft === 1 || this.isFainted()) { switch (result) { - case HitResult.SUPER_EFFECTIVE: - this.scene.queueMessage(i18next.t("battle:hitResultSuperEffective")); - break; - case HitResult.NOT_VERY_EFFECTIVE: - this.scene.queueMessage(i18next.t("battle:hitResultNotVeryEffective")); - break; - case HitResult.ONE_HIT_KO: - this.scene.queueMessage(i18next.t("battle:hitResultOneHitKO")); - break; + case HitResult.SUPER_EFFECTIVE: + this.scene.queueMessage(i18next.t("battle:hitResultSuperEffective")); + break; + case HitResult.NOT_VERY_EFFECTIVE: + this.scene.queueMessage(i18next.t("battle:hitResultNotVeryEffective")); + break; + case HitResult.ONE_HIT_KO: + this.scene.queueMessage(i18next.t("battle:hitResultOneHitKO")); + break; } } if (this.isFainted()) { // set splice index here, so future scene queues happen before FaintedPhase this.scene.setPhaseQueueSplice(); - this.scene.unshiftPhase(new FaintPhase(this.scene, this.getBattlerIndex(), isOneHitKo)); + if (!isNullOrUndefined(destinyTag) && dmg) { + // Destiny Bond will activate during FaintPhase + this.scene.unshiftPhase(new FaintPhase(this.scene, this.getBattlerIndex(), isOneHitKo, destinyTag, source)); + } else { + this.scene.unshiftPhase(new FaintPhase(this.scene, this.getBattlerIndex(), isOneHitKo)); + } this.destroySubstitute(); this.resetSummonData(); } - if (dmg) { - destinyTag?.lapse(source, BattlerTagLapseType.CUSTOM); - } - return result; } } @@ -2870,7 +2897,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } isMax(): boolean { - const maxForms = [SpeciesFormKey.GIGANTAMAX, SpeciesFormKey.GIGANTAMAX_RAPID, SpeciesFormKey.GIGANTAMAX_SINGLE, SpeciesFormKey.ETERNAMAX] as string[]; + const maxForms = [ SpeciesFormKey.GIGANTAMAX, SpeciesFormKey.GIGANTAMAX_RAPID, SpeciesFormKey.GIGANTAMAX_SINGLE, SpeciesFormKey.ETERNAMAX ] as string[]; return maxForms.includes(this.getFormKey()) || (!!this.getFusionFormKey() && maxForms.includes(this.getFusionFormKey()!)); } @@ -3018,6 +3045,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { continue; } + if (tag instanceof PowerTrickTag) { + tag.swapStat(this); + } + this.summonData.tags.push(tag); } @@ -3032,8 +3063,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * * @see {@linkcode MoveRestrictionBattlerTag} */ - isMoveRestricted(moveId: Moves): boolean { - return this.getRestrictingTag(moveId) !== null; + public isMoveRestricted(moveId: Moves, pokemon?: Pokemon): boolean { + return this.getRestrictingTag(moveId, pokemon) !== null; } /** @@ -3066,7 +3097,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { */ getRestrictingTag(moveId: Moves, user?: Pokemon, target?: Pokemon): MoveRestrictionBattlerTag | null { for (const tag of this.findTags(t => t instanceof MoveRestrictionBattlerTag)) { - if ((tag as MoveRestrictionBattlerTag).isMoveRestricted(moveId)) { + if ((tag as MoveRestrictionBattlerTag).isMoveRestricted(moveId, user)) { return tag as MoveRestrictionBattlerTag; } else if (user && target && (tag as MoveRestrictionBattlerTag).isMoveTargetRestricted(moveId, user, target)) { return tag as MoveRestrictionBattlerTag; @@ -3320,53 +3351,53 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } switch (effect) { - case StatusEffect.POISON: - case StatusEffect.TOXIC: + case StatusEffect.POISON: + case StatusEffect.TOXIC: // Check if the Pokemon is immune to Poison/Toxic or if the source pokemon is canceling the immunity - const poisonImmunity = types.map(defType => { + const poisonImmunity = types.map(defType => { // Check if the Pokemon is not immune to Poison/Toxic - if (defType !== Type.POISON && defType !== Type.STEEL) { - return false; - } + if (defType !== Type.POISON && defType !== Type.STEEL) { + return false; + } - // Check if the source Pokemon has an ability that cancels the Poison/Toxic immunity - const cancelImmunity = new Utils.BooleanHolder(false); - if (sourcePokemon) { - applyAbAttrs(IgnoreTypeStatusEffectImmunityAbAttr, sourcePokemon, cancelImmunity, false, effect, defType); - if (cancelImmunity.value) { + // Check if the source Pokemon has an ability that cancels the Poison/Toxic immunity + const cancelImmunity = new Utils.BooleanHolder(false); + if (sourcePokemon) { + applyAbAttrs(IgnoreTypeStatusEffectImmunityAbAttr, sourcePokemon, cancelImmunity, false, effect, defType); + if (cancelImmunity.value) { + return false; + } + } + + return true; + }); + + if (this.isOfType(Type.POISON) || this.isOfType(Type.STEEL)) { + if (poisonImmunity.includes(true)) { return false; } } - - return true; - }); - - if (this.isOfType(Type.POISON) || this.isOfType(Type.STEEL)) { - if (poisonImmunity.includes(true)) { + break; + case StatusEffect.PARALYSIS: + if (this.isOfType(Type.ELECTRIC)) { return false; } - } - break; - case StatusEffect.PARALYSIS: - if (this.isOfType(Type.ELECTRIC)) { - return false; - } - break; - case StatusEffect.SLEEP: - if (this.isGrounded() && this.scene.arena.terrain?.terrainType === TerrainType.ELECTRIC) { - return false; - } - break; - case StatusEffect.FREEZE: - if (this.isOfType(Type.ICE) || (this.scene?.arena?.weather?.weatherType &&[WeatherType.SUNNY, WeatherType.HARSH_SUN].includes(this.scene.arena.weather.weatherType))) { - return false; - } - break; - case StatusEffect.BURN: - if (this.isOfType(Type.FIRE)) { - return false; - } - break; + break; + case StatusEffect.SLEEP: + if (this.isGrounded() && this.scene.arena.terrain?.terrainType === TerrainType.ELECTRIC) { + return false; + } + break; + case StatusEffect.FREEZE: + if (this.isOfType(Type.ICE) || (this.scene?.arena?.weather?.weatherType && [ WeatherType.SUNNY, WeatherType.HARSH_SUN ].includes(this.scene.arena.weather.weatherType))) { + return false; + } + break; + case StatusEffect.BURN: + if (this.isOfType(Type.FIRE)) { + return false; + } + break; } const cancelled = new Utils.BooleanHolder(false); @@ -3651,7 +3682,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { const pixel = pixelData[f].slice(i, i + 4); let [ r, g, b, a ] = pixel; if (variantColors) { - const color = Utils.rgbaToInt([r, g, b, a]); + const color = Utils.rgbaToInt([ r, g, b, a ]); if (variantColorSet.has(color)) { const mappedPixel = variantColorSet.get(color); if (mappedPixel) { @@ -3695,7 +3726,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } let [ r, g, b, a ] = [ pixelData[2 + f][i], pixelData[2 + f][i + 1], pixelData[2 + f][i + 2], pixelData[2 + f][i + 3] ]; if (variantColors) { - const color = Utils.rgbaToInt([r, g, b, a]); + const color = Utils.rgbaToInt([ r, g, b, a ]); if (variantColorSet.has(color)) { const mappedPixel = variantColorSet.get(color); if (mappedPixel) { @@ -3990,7 +4021,7 @@ export class PlayerPokemon extends Pokemon { let compatible = false; for (const p of tmSpecies[tm]) { if (Array.isArray(p)) { - const [pkm, form] = p; + const [ pkm, form ] = p; if ((pkm === this.species.speciesId || this.fusionSpecies && pkm === this.fusionSpecies.speciesId) && form === this.getFormKey()) { compatible = true; break; @@ -4047,7 +4078,7 @@ export class PlayerPokemon extends Pokemon { fusionStarterSpeciesId ? this.scene.gameData.starterData[fusionStarterSpeciesId] : null ].filter(d => !!d); const amount = new Utils.IntegerHolder(friendship); - const starterAmount = new Utils.IntegerHolder(Math.floor(friendship * (this.scene.gameMode.isClassic && friendship > 0 ? 2 : 1) / (fusionStarterSpeciesId ? 2 : 1))); + const starterAmount = new Utils.IntegerHolder(Math.floor(friendship * (this.scene.gameMode.isClassic && friendship > 0 ? CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER : 1) / (fusionStarterSpeciesId ? 2 : 1))); if (amount.value > 0) { this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount); this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount); @@ -4079,7 +4110,7 @@ export class PlayerPokemon extends Pokemon { revivalBlessing(): Promise { return new Promise(resolve => { this.scene.ui.setMode(Mode.PARTY, PartyUiMode.REVIVAL_BLESSING, this.getFieldIndex(), (slotIndex:integer, option: PartyOption) => { - if (slotIndex >= 0 && slotIndex<6) { + if (slotIndex >= 0 && slotIndex < 6) { const pokemon = this.scene.getParty()[slotIndex]; if (!pokemon || !pokemon.isFainted()) { resolve(); @@ -4088,11 +4119,11 @@ export class PlayerPokemon extends Pokemon { pokemon.resetTurnData(); pokemon.resetStatus(); pokemon.heal(Math.min(Utils.toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); - this.scene.queueMessage(i18next.t("moveTriggers:revivalBlessing", {pokemonName: pokemon.name}), 0, true); + this.scene.queueMessage(i18next.t("moveTriggers:revivalBlessing", { pokemonName: pokemon.name }), 0, true); if (this.scene.currentBattle.double && this.scene.getParty().length > 1) { const allyPokemon = this.getAlly(); - if (slotIndex<=1) { + if (slotIndex <= 1) { // Revived ally pokemon this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, SwitchType.SWITCH, pokemon.getFieldIndex(), slotIndex, false, true)); this.scene.unshiftPhase(new ToggleDoublePositionPhase(this.scene, true)); @@ -4159,7 +4190,7 @@ export class PlayerPokemon extends Pokemon { if (!isFusion) { const abilityCount = this.getSpeciesForm().getAbilityCount(); const preEvoAbilityCount = preEvolution.getAbilityCount(); - if ([0, 1, 2].includes(this.abilityIndex)) { + if ([ 0, 1, 2 ].includes(this.abilityIndex)) { // Handles cases where a Pokemon with 3 abilities evolves into a Pokemon with 2 abilities (ie: Eevee -> any Eeveelution) if (this.abilityIndex === 2 && preEvoAbilityCount === 3 && abilityCount === 2) { this.abilityIndex = 1; @@ -4172,7 +4203,7 @@ export class PlayerPokemon extends Pokemon { } else { // Do the same as above, but for fusions const abilityCount = this.getFusionSpeciesForm().getAbilityCount(); const preEvoAbilityCount = preEvolution.getAbilityCount(); - if ([0, 1, 2].includes(this.fusionAbilityIndex)) { + if ([ 0, 1, 2 ].includes(this.fusionAbilityIndex)) { if (this.fusionAbilityIndex === 2 && preEvoAbilityCount === 3 && abilityCount === 2) { this.fusionAbilityIndex = 1; } @@ -4465,35 +4496,35 @@ export class EnemyPokemon extends Pokemon { generateAndPopulateMoveset(formIndex?: integer): void { switch (true) { - case (this.species.speciesId === Species.SMEARGLE): - this.moveset = [ - new PokemonMove(Moves.SKETCH), - new PokemonMove(Moves.SKETCH), - new PokemonMove(Moves.SKETCH), - new PokemonMove(Moves.SKETCH) - ]; - break; - case (this.species.speciesId === Species.ETERNATUS): - this.moveset = (formIndex !== undefined ? formIndex : this.formIndex) - ? [ - new PokemonMove(Moves.DYNAMAX_CANNON), - new PokemonMove(Moves.CROSS_POISON), - new PokemonMove(Moves.FLAMETHROWER), - new PokemonMove(Moves.RECOVER, 0, -4) - ] - : [ - new PokemonMove(Moves.ETERNABEAM), - new PokemonMove(Moves.SLUDGE_BOMB), - new PokemonMove(Moves.FLAMETHROWER), - new PokemonMove(Moves.COSMIC_POWER) + case (this.species.speciesId === Species.SMEARGLE): + this.moveset = [ + new PokemonMove(Moves.SKETCH), + new PokemonMove(Moves.SKETCH), + new PokemonMove(Moves.SKETCH), + new PokemonMove(Moves.SKETCH) ]; - if (this.scene.gameMode.hasChallenge(Challenges.INVERSE_BATTLE)) { - this.moveset[2] = new PokemonMove(Moves.THUNDERBOLT); - } - break; - default: - super.generateAndPopulateMoveset(); - break; + break; + case (this.species.speciesId === Species.ETERNATUS): + this.moveset = (formIndex !== undefined ? formIndex : this.formIndex) + ? [ + new PokemonMove(Moves.DYNAMAX_CANNON), + new PokemonMove(Moves.CROSS_POISON), + new PokemonMove(Moves.FLAMETHROWER), + new PokemonMove(Moves.RECOVER, 0, -4) + ] + : [ + new PokemonMove(Moves.ETERNABEAM), + new PokemonMove(Moves.SLUDGE_BOMB), + new PokemonMove(Moves.FLAMETHROWER), + new PokemonMove(Moves.COSMIC_POWER) + ]; + if (this.scene.gameMode.hasChallenge(Challenges.INVERSE_BATTLE)) { + this.moveset[2] = new PokemonMove(Moves.THUNDERBOLT); + } + break; + default: + super.generateAndPopulateMoveset(); + break; } } @@ -4533,135 +4564,135 @@ export class EnemyPokemon extends Pokemon { } } switch (this.aiType) { - case AiType.RANDOM: // No enemy should spawn with this AI type in-game - const moveId = movePool[this.scene.randBattleSeedInt(movePool.length)]!.moveId; // TODO: is the bang correct? - return { move: moveId, targets: this.getNextTargets(moveId) }; - case AiType.SMART_RANDOM: - case AiType.SMART: + case AiType.RANDOM: // No enemy should spawn with this AI type in-game + const moveId = movePool[this.scene.randBattleSeedInt(movePool.length)]!.moveId; // TODO: is the bang correct? + return { move: moveId, targets: this.getNextTargets(moveId) }; + case AiType.SMART_RANDOM: + case AiType.SMART: /** * Search this Pokemon's move pool for moves that will KO an opposing target. * If there are any moves that can KO an opponent (i.e. a player Pokemon), * those moves are the only ones considered for selection on this turn. */ - const koMoves = movePool.filter(pkmnMove => { - if (!pkmnMove) { - return false; - } + const koMoves = movePool.filter(pkmnMove => { + if (!pkmnMove) { + return false; + } - const move = pkmnMove.getMove()!; - if (move.moveTarget === MoveTarget.ATTACKER) { - return false; - } + const move = pkmnMove.getMove()!; + if (move.moveTarget === MoveTarget.ATTACKER) { + return false; + } - const fieldPokemon = this.scene.getField(); - const moveTargets = getMoveTargets(this, move.id).targets - .map(ind => fieldPokemon[ind]) - .filter(p => this.isPlayer() !== p.isPlayer()); - // Only considers critical hits for crit-only moves or when this Pokemon is under the effect of Laser Focus - const isCritical = move.hasAttr(CritOnlyAttr) || !!this.getTag(BattlerTagType.ALWAYS_CRIT); + const fieldPokemon = this.scene.getField(); + const moveTargets = getMoveTargets(this, move.id).targets + .map(ind => fieldPokemon[ind]) + .filter(p => this.isPlayer() !== p.isPlayer()); + // Only considers critical hits for crit-only moves or when this Pokemon is under the effect of Laser Focus + const isCritical = move.hasAttr(CritOnlyAttr) || !!this.getTag(BattlerTagType.ALWAYS_CRIT); - return move.category !== MoveCategory.STATUS + return move.category !== MoveCategory.STATUS && moveTargets.some(p => { - const doesNotFail = move.applyConditions(this, p, move) || [Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP].includes(move.id); + const doesNotFail = move.applyConditions(this, p, move) || [ Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP ].includes(move.id); return doesNotFail && p.getAttackDamage(this, move, !p.battleData.abilityRevealed, false, isCritical).damage >= p.hp; }); - }, this); + }, this); - if (koMoves.length > 0) { - movePool = koMoves; - } + if (koMoves.length > 0) { + movePool = koMoves; + } - /** + /** * Move selection is based on the move's calculated "benefit score" against the * best possible target(s) (as determined by {@linkcode getNextTargets}). * For more information on how benefit scores are calculated, see `docs/enemy-ai.md`. */ - const moveScores = movePool.map(() => 0); - const moveTargets = Object.fromEntries(movePool.map(m => [ m!.moveId, this.getNextTargets(m!.moveId) ])); // TODO: are those bangs correct? - for (const m in movePool) { - const pokemonMove = movePool[m]!; // TODO: is the bang correct? - const move = pokemonMove.getMove(); + const moveScores = movePool.map(() => 0); + const moveTargets = Object.fromEntries(movePool.map(m => [ m!.moveId, this.getNextTargets(m!.moveId) ])); // TODO: are those bangs correct? + for (const m in movePool) { + const pokemonMove = movePool[m]!; // TODO: is the bang correct? + const move = pokemonMove.getMove(); - let moveScore = moveScores[m]; - const targetScores: integer[] = []; + let moveScore = moveScores[m]; + const targetScores: integer[] = []; - for (const mt of moveTargets[move.id]) { + for (const mt of moveTargets[move.id]) { // Prevent a target score from being calculated when the target is whoever attacks the user - if (mt === BattlerIndex.ATTACKER) { - break; - } + if (mt === BattlerIndex.ATTACKER) { + break; + } - const target = this.scene.getField()[mt]; - /** + const target = this.scene.getField()[mt]; + /** * The "target score" of a move is given by the move's user benefit score + the move's target benefit score. * If the target is an ally, the target benefit score is multiplied by -1. */ - let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1); - if (Number.isNaN(targetScore)) { - console.error(`Move ${move.name} returned score of NaN`); - targetScore = 0; - } - /** + let targetScore = move.getUserBenefitScore(this, target, move) + move.getTargetBenefitScore(this, target, move) * (mt < BattlerIndex.ENEMY === this.isPlayer() ? 1 : -1); + if (Number.isNaN(targetScore)) { + console.error(`Move ${move.name} returned score of NaN`); + targetScore = 0; + } + /** * If this move is unimplemented, or the move is known to fail when used, set its * target score to -20 */ - if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP].includes(move.id)) { - targetScore = -20; - } else if (move instanceof AttackMove) { + if ((move.name.endsWith(" (N)") || !move.applyConditions(this, target, move)) && ![ Moves.SUCKER_PUNCH, Moves.UPPER_HAND, Moves.THUNDERCLAP ].includes(move.id)) { + targetScore = -20; + } else if (move instanceof AttackMove) { /** * Attack moves are given extra multipliers to their base benefit score based on * the move's type effectiveness against the target and whether the move is a STAB move. */ - const effectiveness = target.getMoveEffectiveness(this, move, !target.battleData?.abilityRevealed); - if (target.isPlayer() !== this.isPlayer()) { - targetScore *= effectiveness; - if (this.isOfType(move.type)) { - targetScore *= 1.5; + const effectiveness = target.getMoveEffectiveness(this, move, !target.battleData?.abilityRevealed); + if (target.isPlayer() !== this.isPlayer()) { + targetScore *= effectiveness; + if (this.isOfType(move.type)) { + targetScore *= 1.5; + } + } else if (effectiveness) { + targetScore /= effectiveness; + if (this.isOfType(move.type)) { + targetScore /= 1.5; + } } - } else if (effectiveness) { - targetScore /= effectiveness; - if (this.isOfType(move.type)) { - targetScore /= 1.5; + /** If a move has a base benefit score of 0, its benefit score is assumed to be unimplemented at this point */ + if (!targetScore) { + targetScore = -20; } } - /** If a move has a base benefit score of 0, its benefit score is assumed to be unimplemented at this point */ - if (!targetScore) { - targetScore = -20; - } + targetScores.push(targetScore); } - targetScores.push(targetScore); + // When a move has multiple targets, its score is equal to the maximum target score across all targets + moveScore += Math.max(...targetScores); + + // could make smarter by checking opponent def/spdef + moveScores[m] = moveScore; } - // When a move has multiple targets, its score is equal to the maximum target score across all targets - moveScore += Math.max(...targetScores); - // could make smarter by checking opponent def/spdef - moveScores[m] = moveScore; - } + console.log(moveScores); - console.log(moveScores); - - // Sort the move pool in decreasing order of move score - const sortedMovePool = movePool.slice(0); - sortedMovePool.sort((a, b) => { - const scoreA = moveScores[movePool.indexOf(a)]; - const scoreB = moveScores[movePool.indexOf(b)]; - return scoreA < scoreB ? 1 : scoreA > scoreB ? -1 : 0; - }); - let r = 0; - if (this.aiType === AiType.SMART_RANDOM) { + // Sort the move pool in decreasing order of move score + const sortedMovePool = movePool.slice(0); + sortedMovePool.sort((a, b) => { + const scoreA = moveScores[movePool.indexOf(a)]; + const scoreB = moveScores[movePool.indexOf(b)]; + return scoreA < scoreB ? 1 : scoreA > scoreB ? -1 : 0; + }); + let r = 0; + if (this.aiType === AiType.SMART_RANDOM) { // Has a 5/8 chance to select the best move, and a 3/8 chance to advance to the next best move (and repeat this roll) - while (r < sortedMovePool.length - 1 && this.scene.randBattleSeedInt(8) >= 5) { - r++; - } - } else if (this.aiType === AiType.SMART) { + while (r < sortedMovePool.length - 1 && this.scene.randBattleSeedInt(8) >= 5) { + r++; + } + } else if (this.aiType === AiType.SMART) { // The chance to advance to the next best move increases when the compared moves' scores are closer to each other. - while (r < sortedMovePool.length - 1 && (moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) >= 0 + while (r < sortedMovePool.length - 1 && (moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) >= 0 && this.scene.randBattleSeedInt(100) < Math.round((moveScores[movePool.indexOf(sortedMovePool[r + 1])] / moveScores[movePool.indexOf(sortedMovePool[r])]) * 50)) { - r++; + r++; + } } - } - console.log(movePool.map(m => m!.getName()), moveScores, r, sortedMovePool.map(m => m!.getName())); // TODO: are those bangs correct? - return { move: sortedMovePool[r]!.moveId, targets: moveTargets[sortedMovePool[r]!.moveId] }; + console.log(movePool.map(m => m!.getName()), moveScores, r, sortedMovePool.map(m => m!.getName())); // TODO: are those bangs correct? + return { move: sortedMovePool[r]!.moveId, targets: moveTargets[sortedMovePool[r]!.moveId] }; } } @@ -4701,7 +4732,7 @@ export class EnemyPokemon extends Pokemon { // Set target to BattlerIndex.ATTACKER when using a counter move // This is the same as when the player does so if (move.hasAttr(CounterDamageAttr)) { - return [BattlerIndex.ATTACKER]; + return [ BattlerIndex.ATTACKER ]; } return []; @@ -4809,10 +4840,10 @@ export class EnemyPokemon extends Pokemon { } switch (this.scene.currentBattle.battleSpec) { - case BattleSpec.FINAL_BOSS: - if (!this.formIndex && this.bossSegmentIndex < 1) { - damage = Math.min(damage, this.hp - 1); - } + case BattleSpec.FINAL_BOSS: + if (!this.formIndex && this.bossSegmentIndex < 1) { + damage = Math.min(damage, this.hp - 1); + } } const ret = super.damage(damage, ignoreSegments, preventEndure, ignoreFaintPhase); @@ -5015,8 +5046,12 @@ export class PokemonBattleSummonData { export class PokemonTurnData { public flinched: boolean = false; public acted: boolean = false; - public hitCount: number; - public hitsLeft: number; + public hitCount: number = 0; + /** + * - `-1` = Calculate how many hits are left + * - `0` = Move is finished + */ + public hitsLeft: number = -1; public damageDealt: number = 0; public currDamageDealt: number = 0; public damageTaken: number = 0; @@ -5025,6 +5060,7 @@ export class PokemonTurnData { public statStagesIncreased: boolean = false; public statStagesDecreased: boolean = false; public moveEffectiveness: TypeDamageMultiplier | null = null; + public combiningPledge?: Moves; } export enum AiType { @@ -5102,8 +5138,8 @@ export class PokemonMove { * @param {boolean} ignoreRestrictionTags If `true`, skips the check for move restriction tags (see {@link MoveRestrictionBattlerTag}) * @returns `true` if the move can be selected and used by the Pokemon, otherwise `false`. */ - isUsable(pokemon: Pokemon, ignorePp?: boolean, ignoreRestrictionTags?: boolean): boolean { - if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId)) { + isUsable(pokemon: Pokemon, ignorePp: boolean = false, ignoreRestrictionTags: boolean = false): boolean { + if (this.moveId && !ignoreRestrictionTags && pokemon.isMoveRestricted(this.moveId, pokemon)) { return false; } diff --git a/src/field/trainer.ts b/src/field/trainer.ts index 06548e2b020..b77a156f401 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -1,6 +1,6 @@ import BattleScene from "#app/battle-scene"; -import {pokemonPrevolutions} from "#app/data/balance/pokemon-evolutions"; -import PokemonSpecies, {getPokemonSpecies} from "#app/data/pokemon-species"; +import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; +import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species"; import { TrainerConfig, TrainerPartyCompoundTemplate, @@ -11,7 +11,7 @@ import { trainerPartyTemplates, signatureSpecies } from "#app/data/trainer-config"; -import {EnemyPokemon} from "#app/field/pokemon"; +import { EnemyPokemon } from "#app/field/pokemon"; import * as Utils from "#app/utils"; import { PersistentModifier } from "#app/modifier/modifier"; import { trainerNamePools } from "#app/data/trainer-names"; @@ -56,7 +56,7 @@ export default class Trainer extends Phaser.GameObjects.Container { if (partnerName) { this.partnerName = partnerName; } else { - [this.name, this.partnerName] = this.name.split(" & "); + [ this.name, this.partnerName ] = this.name.split(" & "); } } else { this.partnerName = partnerName || Utils.randSeedItem(Array.isArray(namePool[0]) ? namePool[1] : namePool); @@ -65,16 +65,16 @@ export default class Trainer extends Phaser.GameObjects.Container { } switch (this.variant) { - case TrainerVariant.FEMALE: - if (!this.config.hasGenders) { - variant = TrainerVariant.DEFAULT; - } - break; - case TrainerVariant.DOUBLE: - if (!this.config.hasDouble) { - variant = TrainerVariant.DEFAULT; - } - break; + case TrainerVariant.FEMALE: + if (!this.config.hasGenders) { + variant = TrainerVariant.DEFAULT; + } + break; + case TrainerVariant.DOUBLE: + if (!this.config.hasDouble) { + variant = TrainerVariant.DEFAULT; + } + break; } console.log(Object.keys(trainerPartyTemplates)[Object.values(trainerPartyTemplates).indexOf(this.getPartyTemplate())]); @@ -82,7 +82,7 @@ export default class Trainer extends Phaser.GameObjects.Container { const getSprite = (hasShadow?: boolean, forceFemale?: boolean) => { const ret = this.scene.addFieldSprite(0, 0, this.config.getSpriteKey(variant === TrainerVariant.FEMALE || forceFemale, this.isDouble())); ret.setOrigin(0.5, 1); - ret.setPipeline(this.scene.spritePipeline, {tone: [0.0, 0.0, 0.0, 0.0], hasShadow: !!hasShadow}); + ret.setPipeline(this.scene.spritePipeline, { tone: [ 0.0, 0.0, 0.0, 0.0 ], hasShadow: !!hasShadow }); return ret; }; @@ -126,7 +126,7 @@ export default class Trainer extends Phaser.GameObjects.Container { // Determine the title to include based on the configuration and includeTitle flag. let title = includeTitle && this.config.title ? this.config.title : null; - const evilTeamTitles = ["grunt"]; + const evilTeamTitles = [ "grunt" ]; if (this.name === "" && evilTeamTitles.some(t => name.toLocaleLowerCase().includes(t))) { // This is a evil team grunt so we localize it by only using the "name" as the title title = i18next.t(`trainerClasses:${name.toLowerCase().replace(/\s/g, "_")}`); @@ -229,21 +229,21 @@ export default class Trainer extends Phaser.GameObjects.Container { const strength = partyTemplate.getStrength(i); switch (strength) { - case PartyMemberStrength.WEAKER: - multiplier = 0.95; - break; - case PartyMemberStrength.WEAK: - multiplier = 1.0; - break; - case PartyMemberStrength.AVERAGE: - multiplier = 1.1; - break; - case PartyMemberStrength.STRONG: - multiplier = 1.2; - break; - case PartyMemberStrength.STRONGER: - multiplier = 1.25; - break; + case PartyMemberStrength.WEAKER: + multiplier = 0.95; + break; + case PartyMemberStrength.WEAK: + multiplier = 1.0; + break; + case PartyMemberStrength.AVERAGE: + multiplier = 1.1; + break; + case PartyMemberStrength.STRONG: + multiplier = 1.2; + break; + case PartyMemberStrength.STRONGER: + multiplier = 1.25; + break; } let levelOffset = 0; @@ -336,9 +336,9 @@ export default class Trainer extends Phaser.GameObjects.Container { if (!(index % 2)) { // Since the only currently allowed double battle with named trainers is Tate & Liza, we need to make sure that Solrock is the first pokemon in the party for Tate and Lunatone for Liza if (index === 0 && (TrainerType[this.config.trainerType] === TrainerType[TrainerType.TATE])) { - newSpeciesPool = [Species.SOLROCK]; + newSpeciesPool = [ Species.SOLROCK ]; } else if (index === 0 && (TrainerType[this.config.trainerType] === TrainerType[TrainerType.LIZA])) { - newSpeciesPool = [Species.LUNATONE]; + newSpeciesPool = [ Species.LUNATONE ]; } else { newSpeciesPool = speciesPoolFiltered; } @@ -346,9 +346,9 @@ export default class Trainer extends Phaser.GameObjects.Container { // If the index is odd, use the species pool for the partner trainer (that way he only uses his own pokemon in battle) // Since the only currently allowed double battle with named trainers is Tate & Liza, we need to make sure that Solrock is the first pokemon in the party for Tate and Lunatone for Liza if (index === 1 && (TrainerType[this.config.trainerTypeDouble] === TrainerType[TrainerType.TATE])) { - newSpeciesPool = [Species.SOLROCK]; + newSpeciesPool = [ Species.SOLROCK ]; } else if (index === 1 && (TrainerType[this.config.trainerTypeDouble] === TrainerType[TrainerType.LIZA])) { - newSpeciesPool = [Species.LUNATONE]; + newSpeciesPool = [ Species.LUNATONE ]; } else { newSpeciesPool = speciesPoolPartnerFiltered; } @@ -383,7 +383,7 @@ export default class Trainer extends Phaser.GameObjects.Container { const battle = this.scene.currentBattle; const template = this.getPartyTemplate(); - let species: PokemonSpecies; + let baseSpecies: PokemonSpecies; if (this.config.speciesPools) { const tierValue = Utils.randSeedInt(512); let tier = tierValue >= 156 ? TrainerPoolTier.COMMON : tierValue >= 32 ? TrainerPoolTier.UNCOMMON : tierValue >= 6 ? TrainerPoolTier.RARE : tierValue >= 1 ? TrainerPoolTier.SUPER_RARE : TrainerPoolTier.ULTRA_RARE; @@ -393,17 +393,17 @@ export default class Trainer extends Phaser.GameObjects.Container { tier--; } const tierPool = this.config.speciesPools[tier]; - species = getPokemonSpecies(Utils.randSeedItem(tierPool)); + baseSpecies = getPokemonSpecies(Utils.randSeedItem(tierPool)); } else { - species = this.scene.randomSpecies(battle.waveIndex, level, false, this.config.speciesFilter); + baseSpecies = this.scene.randomSpecies(battle.waveIndex, level, false, this.config.speciesFilter); } - let ret = getPokemonSpecies(species.getTrainerSpeciesForLevel(level, true, strength, this.scene.currentBattle.waveIndex)); + let ret = getPokemonSpecies(baseSpecies.getTrainerSpeciesForLevel(level, true, strength, this.scene.currentBattle.waveIndex)); let retry = false; console.log(ret.getName()); - if (pokemonPrevolutions.hasOwnProperty(species.speciesId) && ret.speciesId !== species.speciesId) { + if (pokemonPrevolutions.hasOwnProperty(baseSpecies.speciesId) && ret.speciesId !== baseSpecies.speciesId) { retry = true; } else if (template.isBalanced(battle.enemyParty.length)) { const partyMemberTypes = battle.enemyParty.map(p => p.getTypes(true)).flat(); @@ -417,7 +417,7 @@ export default class Trainer extends Phaser.GameObjects.Container { console.log("Attempting reroll of species evolution to fit specialty type..."); let evoAttempt = 0; while (retry && evoAttempt++ < 10) { - ret = getPokemonSpecies(species.getTrainerSpeciesForLevel(level, true, strength, this.scene.currentBattle.waveIndex)); + ret = getPokemonSpecies(baseSpecies.getTrainerSpeciesForLevel(level, true, strength, this.scene.currentBattle.waveIndex)); console.log(ret.name); if (this.config.specialtyTypes.find(t => ret.isOfType(t))) { retry = false; @@ -426,7 +426,7 @@ export default class Trainer extends Phaser.GameObjects.Container { } // Prompts reroll of party member species if species already present in the enemy party - if (this.checkDuplicateSpecies(ret)) { + if (this.checkDuplicateSpecies(ret, baseSpecies)) { console.log("Duplicate species detected, prompting reroll..."); retry = true; } @@ -442,13 +442,16 @@ export default class Trainer extends Phaser.GameObjects.Container { /** * Checks if the enemy trainer already has the Pokemon species in their party * @param {PokemonSpecies} species {@linkcode PokemonSpecies} + * @param {PokemonSpecies} baseSpecies {@linkcode PokemonSpecies} - baseSpecies of the Pokemon if species is forced to evolve * @returns `true` if the species is already present in the party */ - checkDuplicateSpecies(species: PokemonSpecies): boolean { + checkDuplicateSpecies(species: PokemonSpecies, baseSpecies: PokemonSpecies): boolean { + const staticPartyPokemon = (signatureSpecies[TrainerType[this.config.trainerType]] ?? []).flat(1); + const currentPartySpecies = this.scene.getEnemyParty().map(p => { return p.species.speciesId; }); - return currentPartySpecies.includes(species.speciesId); + return currentPartySpecies.includes(species.speciesId) || staticPartyPokemon.includes(baseSpecies.speciesId); } getPartyMemberMatchupScores(trainerSlot: TrainerSlot = TrainerSlot.NONE, forSwitch: boolean = false): [integer, integer][] { @@ -475,7 +478,7 @@ export default class Trainer extends Phaser.GameObjects.Container { } } - return [party.indexOf(p), score]; + return [ party.indexOf(p), score ]; }) as [integer, integer][]; return partyMemberScores; @@ -512,19 +515,19 @@ export default class Trainer extends Phaser.GameObjects.Container { getPartyMemberModifierChanceMultiplier(index: integer): number { switch (this.getPartyTemplate().getStrength(index)) { - case PartyMemberStrength.WEAKER: - return 0.75; - case PartyMemberStrength.WEAK: - return 0.675; - case PartyMemberStrength.AVERAGE: - return 0.5625; - case PartyMemberStrength.STRONG: - return 0.45; - case PartyMemberStrength.STRONGER: - return 0.375; - default: - console.warn("getPartyMemberModifierChanceMultiplier not defined. Using default 0"); - return 0; + case PartyMemberStrength.WEAKER: + return 0.75; + case PartyMemberStrength.WEAK: + return 0.675; + case PartyMemberStrength.AVERAGE: + return 0.5625; + case PartyMemberStrength.STRONG: + return 0.45; + case PartyMemberStrength.STRONGER: + return 0.375; + default: + console.warn("getPartyMemberModifierChanceMultiplier not defined. Using default 0"); + return 0; } } diff --git a/src/game-mode.ts b/src/game-mode.ts index 525c975a19b..8f1bb9356e6 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -33,8 +33,8 @@ interface GameModeConfig { } // Describes min and max waves for MEs in specific game modes -export const CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES: [number, number] = [10, 180]; -export const CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES: [number, number] = [10, 180]; +export const CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES: [number, number] = [ 10, 180 ]; +export const CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES: [number, number] = [ 10, 180 ]; export class GameMode implements GameModeConfig { public modeId: GameModes; @@ -92,10 +92,10 @@ export class GameMode implements GameModeConfig { return Overrides.STARTING_LEVEL_OVERRIDE; } switch (this.modeId) { - case GameModes.DAILY: - return 20; - default: - return 5; + case GameModes.DAILY: + return 20; + default: + return 5; } } @@ -117,19 +117,19 @@ export class GameMode implements GameModeConfig { */ getStartingBiome(scene: BattleScene): Biome { switch (this.modeId) { - case GameModes.DAILY: - return scene.generateRandomBiome(this.getWaveForDifficulty(1)); - default: - return Overrides.STARTING_BIOME_OVERRIDE || Biome.TOWN; + case GameModes.DAILY: + return scene.generateRandomBiome(this.getWaveForDifficulty(1)); + default: + return Overrides.STARTING_BIOME_OVERRIDE || Biome.TOWN; } } getWaveForDifficulty(waveIndex: integer, ignoreCurveChanges: boolean = false): integer { switch (this.modeId) { - case GameModes.DAILY: - return waveIndex + 30 + (!ignoreCurveChanges ? Math.floor(waveIndex / 5) : 0); - default: - return waveIndex; + case GameModes.DAILY: + return waveIndex + 30 + (!ignoreCurveChanges ? Math.floor(waveIndex / 5) : 0); + default: + return waveIndex; } } @@ -186,10 +186,10 @@ export class GameMode implements GameModeConfig { isTrainerBoss(waveIndex: integer, biomeType: Biome, offsetGym: boolean): boolean { switch (this.modeId) { - case GameModes.DAILY: - return waveIndex > 10 && waveIndex < 50 && !(waveIndex % 10); - default: - return (waveIndex % 30) === (offsetGym ? 0 : 20) && (biomeType !== Biome.END || this.isClassic || this.isWaveFinal(waveIndex)); + case GameModes.DAILY: + return waveIndex > 10 && waveIndex < 50 && !(waveIndex % 10); + default: + return (waveIndex % 30) === (offsetGym ? 0 : 20) && (biomeType !== Biome.END || this.isClassic || this.isWaveFinal(waveIndex)); } } @@ -211,14 +211,14 @@ export class GameMode implements GameModeConfig { */ isWaveFinal(waveIndex: integer, modeId: GameModes = this.modeId): boolean { switch (modeId) { - case GameModes.CLASSIC: - case GameModes.CHALLENGE: - return waveIndex === 200; - case GameModes.ENDLESS: - case GameModes.SPLICED_ENDLESS: - return !(waveIndex % 250); - case GameModes.DAILY: - return waveIndex === 50; + case GameModes.CLASSIC: + case GameModes.CHALLENGE: + return waveIndex === 200; + case GameModes.ENDLESS: + case GameModes.SPLICED_ENDLESS: + return !(waveIndex % 250); + case GameModes.DAILY: + return waveIndex === 50; } } @@ -287,40 +287,40 @@ export class GameMode implements GameModeConfig { getClearScoreBonus(): integer { switch (this.modeId) { - case GameModes.CLASSIC: - case GameModes.CHALLENGE: - return 5000; - case GameModes.DAILY: - return 2500; - default: - return 0; + case GameModes.CLASSIC: + case GameModes.CHALLENGE: + return 5000; + case GameModes.DAILY: + return 2500; + default: + return 0; } } getEnemyModifierChance(isBoss: boolean): integer { switch (this.modeId) { - case GameModes.CLASSIC: - case GameModes.CHALLENGE: - case GameModes.DAILY: - return !isBoss ? 18 : 6; - case GameModes.ENDLESS: - case GameModes.SPLICED_ENDLESS: - return !isBoss ? 12 : 4; + case GameModes.CLASSIC: + case GameModes.CHALLENGE: + case GameModes.DAILY: + return !isBoss ? 18 : 6; + case GameModes.ENDLESS: + case GameModes.SPLICED_ENDLESS: + return !isBoss ? 12 : 4; } } getName(): string { switch (this.modeId) { - case GameModes.CLASSIC: - return i18next.t("gameMode:classic"); - case GameModes.ENDLESS: - return i18next.t("gameMode:endless"); - case GameModes.SPLICED_ENDLESS: - return i18next.t("gameMode:endlessSpliced"); - case GameModes.DAILY: - return i18next.t("gameMode:dailyRun"); - case GameModes.CHALLENGE: - return i18next.t("gameMode:challenge"); + case GameModes.CLASSIC: + return i18next.t("gameMode:classic"); + case GameModes.ENDLESS: + return i18next.t("gameMode:endless"); + case GameModes.SPLICED_ENDLESS: + return i18next.t("gameMode:endlessSpliced"); + case GameModes.DAILY: + return i18next.t("gameMode:dailyRun"); + case GameModes.CHALLENGE: + return i18next.t("gameMode:challenge"); } } @@ -329,42 +329,42 @@ export class GameMode implements GameModeConfig { */ getMysteryEncounterLegalWaves(): [number, number] { switch (this.modeId) { - default: - return [0, 0]; - case GameModes.CLASSIC: - return CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES; - case GameModes.CHALLENGE: - return CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES; + default: + return [ 0, 0 ]; + case GameModes.CLASSIC: + return CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES; + case GameModes.CHALLENGE: + return CHALLENGE_MODE_MYSTERY_ENCOUNTER_WAVES; } } static getModeName(modeId: GameModes): string { switch (modeId) { - case GameModes.CLASSIC: - return i18next.t("gameMode:classic"); - case GameModes.ENDLESS: - return i18next.t("gameMode:endless"); - case GameModes.SPLICED_ENDLESS: - return i18next.t("gameMode:endlessSpliced"); - case GameModes.DAILY: - return i18next.t("gameMode:dailyRun"); - case GameModes.CHALLENGE: - return i18next.t("gameMode:challenge"); + case GameModes.CLASSIC: + return i18next.t("gameMode:classic"); + case GameModes.ENDLESS: + return i18next.t("gameMode:endless"); + case GameModes.SPLICED_ENDLESS: + return i18next.t("gameMode:endlessSpliced"); + case GameModes.DAILY: + return i18next.t("gameMode:dailyRun"); + case GameModes.CHALLENGE: + return i18next.t("gameMode:challenge"); } } } export function getGameMode(gameMode: GameModes): GameMode { switch (gameMode) { - case GameModes.CLASSIC: - return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasMysteryEncounters: true }, classicFixedBattles); - case GameModes.ENDLESS: - return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true }); - case GameModes.SPLICED_ENDLESS: - return new GameMode(GameModes.SPLICED_ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true, isSplicedOnly: true }); - case GameModes.DAILY: - return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true }); - case GameModes.CHALLENGE: - return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true, hasMysteryEncounters: true }, classicFixedBattles); + case GameModes.CLASSIC: + return new GameMode(GameModes.CLASSIC, { isClassic: true, hasTrainers: true, hasMysteryEncounters: true }, classicFixedBattles); + case GameModes.ENDLESS: + return new GameMode(GameModes.ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true }); + case GameModes.SPLICED_ENDLESS: + return new GameMode(GameModes.SPLICED_ENDLESS, { isEndless: true, hasShortBiomes: true, hasRandomBosses: true, isSplicedOnly: true }); + case GameModes.DAILY: + return new GameMode(GameModes.DAILY, { isDaily: true, hasTrainers: true, hasNoShop: true }); + case GameModes.CHALLENGE: + return new GameMode(GameModes.CHALLENGE, { isClassic: true, hasTrainers: true, isChallenge: true, hasMysteryEncounters: true }, classicFixedBattles); } } diff --git a/src/inputs-controller.ts b/src/inputs-controller.ts index bb3cfcbeb3b..537d2870259 100644 --- a/src/inputs-controller.ts +++ b/src/inputs-controller.ts @@ -1,12 +1,12 @@ import Phaser from "phaser"; import * as Utils from "./utils"; -import {deepCopy} from "./utils"; +import { deepCopy } from "./utils"; import pad_generic from "./configs/inputs/pad_generic"; import pad_unlicensedSNES from "./configs/inputs/pad_unlicensedSNES"; import pad_xbox360 from "./configs/inputs/pad_xbox360"; import pad_dualshock from "./configs/inputs/pad_dualshock"; import pad_procon from "./configs/inputs/pad_procon"; -import {Mode} from "./ui/ui"; +import { Mode } from "./ui/ui"; import SettingsGamepadUiHandler from "./ui/settings/settings-gamepad-ui-handler"; import SettingsKeyboardUiHandler from "./ui/settings/settings-keyboard-ui-handler"; import cfg_keyboard_qwerty from "./configs/inputs/cfg_keyboard_qwerty"; @@ -16,8 +16,8 @@ import { getIconForLatestInput, swap, } from "#app/configs/inputs/configHandler"; import BattleScene from "./battle-scene"; -import {SettingGamepad} from "#app/system/settings/settings-gamepad"; -import {SettingKeyboard} from "#app/system/settings/settings-keyboard"; +import { SettingGamepad } from "#app/system/settings/settings-gamepad"; +import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; import TouchControl from "#app/touch-controls"; import { Button } from "#enums/buttons"; import { Device } from "#enums/devices"; @@ -294,7 +294,7 @@ export class InputsController { this.setChosenGamepad(gamepadID); } const config = deepCopy(this.getConfig(gamepadID)) as InterfaceConfig; - config.custom = this.configs[gamepadID]?.custom || {...config.default}; + config.custom = this.configs[gamepadID]?.custom || { ...config.default }; this.configs[gamepadID] = config; this.scene.gameData?.saveMappingConfigs(gamepadID, this.configs[gamepadID]); } @@ -307,9 +307,9 @@ export class InputsController { * Initializes or updates configurations for connected keyboards. */ setupKeyboard(): void { - for (const layout of ["default"]) { + for (const layout of [ "default" ]) { const config = deepCopy(this.getConfigKeyboard(layout)) as InterfaceConfig; - config.custom = this.configs[layout]?.custom || {...config.default}; + config.custom = this.configs[layout]?.custom || { ...config.default }; this.configs[layout] = config; this.scene.gameData?.saveMappingConfigs(this.selectedDevice[Device.KEYBOARD], this.configs[layout]); } @@ -330,7 +330,7 @@ export class InputsController { return el !== null; }) ?? []; - for (const [index, thisGamepad] of this.gamepads.entries()) { + for (const [ index, thisGamepad ] of this.gamepads.entries()) { thisGamepad.index = index; // Overwrite the gamepad index, in case we had undefined gamepads earlier } } diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 3d4f4d165e6..4f673fd2cfc 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -19,7 +19,7 @@ import i18next from "i18next"; import { initStatsKeys } from "#app/ui/game-stats-ui-handler"; import { initVouchers } from "#app/system/voucher"; import { Biome } from "#enums/biome"; -import {initMysteryEncounters} from "#app/data/mystery-encounters/mystery-encounters"; +import { initMysteryEncounters } from "#app/data/mystery-encounters/mystery-encounters"; export class LoadingScene extends SceneBase { public static readonly KEY = "loading"; @@ -242,9 +242,9 @@ export class LoadingScene extends SceneBase { this.loadAtlas("statuses", ""); this.loadAtlas("types", ""); } - const availableLangs = ["en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN"]; + const availableLangs = [ "en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN" ]; if (lang && availableLangs.includes(lang)) { - this.loadImage("egg-update_"+lang, "events"); + this.loadImage("egg-update_" + lang, "events"); } else { this.loadImage("egg-update_en", "events"); } @@ -477,18 +477,18 @@ export class LoadingScene extends SceneBase { this.load.on(this.LOAD_EVENTS.FILE_COMPLETE, (key: string) => { assetText.setText(i18next.t("menu:loadingAsset", { assetName: key })); switch (key) { - case "loading_bg": - bg.setTexture("loading_bg"); - if (mobile) { - bg.setVisible(true); - } - break; - case "logo": - logo.setTexture("logo"); - if (mobile) { - logo.setVisible(true); - } - break; + case "loading_bg": + bg.setTexture("loading_bg"); + if (mobile) { + bg.setVisible(true); + } + break; + case "logo": + logo.setTexture("logo"); + if (mobile) { + logo.setVisible(true); + } + break; } }); diff --git a/src/messages.ts b/src/messages.ts index 1cd6a5966b6..91f550918e5 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -13,21 +13,21 @@ export function getPokemonNameWithAffix(pokemon: Pokemon | undefined): string { } switch (pokemon.scene.currentBattle.battleSpec) { - case BattleSpec.DEFAULT: - return !pokemon.isPlayer() - ? pokemon.hasTrainer() - ? i18next.t("battle:foePokemonWithAffix", { - pokemonName: pokemon.getNameToRender(), - }) - : i18next.t("battle:wildPokemonWithAffix", { - pokemonName: pokemon.getNameToRender(), - }) - : pokemon.getNameToRender(); - case BattleSpec.FINAL_BOSS: - return !pokemon.isPlayer() - ? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender() }) - : pokemon.getNameToRender(); - default: - return pokemon.getNameToRender(); + case BattleSpec.DEFAULT: + return !pokemon.isPlayer() + ? pokemon.hasTrainer() + ? i18next.t("battle:foePokemonWithAffix", { + pokemonName: pokemon.getNameToRender(), + }) + : i18next.t("battle:wildPokemonWithAffix", { + pokemonName: pokemon.getNameToRender(), + }) + : pokemon.getNameToRender(); + case BattleSpec.FINAL_BOSS: + return !pokemon.isPlayer() + ? i18next.t("battle:foePokemonWithAffix", { pokemonName: pokemon.getNameToRender() }) + : pokemon.getNameToRender(); + default: + return pokemon.getNameToRender(); } } diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index 244c5e5cc3e..1310f815f79 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -80,18 +80,18 @@ export class ModifierType { } let poolTypes: ModifierPoolType[]; switch (poolType) { - case ModifierPoolType.PLAYER: - poolTypes = [ poolType, ModifierPoolType.TRAINER, ModifierPoolType.WILD ]; - break; - case ModifierPoolType.WILD: - poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.TRAINER ]; - break; - case ModifierPoolType.TRAINER: - poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.WILD ]; - break; - default: - poolTypes = [ poolType ]; - break; + case ModifierPoolType.PLAYER: + poolTypes = [ poolType, ModifierPoolType.TRAINER, ModifierPoolType.WILD ]; + break; + case ModifierPoolType.WILD: + poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.TRAINER ]; + break; + case ModifierPoolType.TRAINER: + poolTypes = [ poolType, ModifierPoolType.PLAYER, ModifierPoolType.WILD ]; + break; + default: + poolTypes = [ poolType ]; + break; } // Try multiple pool types in case of stolen items for (const type of poolTypes) { @@ -504,42 +504,42 @@ export class BerryModifierType extends PokemonHeldItemModifierType implements Ge function getAttackTypeBoosterItemName(type: Type) { switch (type) { - case Type.NORMAL: - return "Silk Scarf"; - case Type.FIGHTING: - return "Black Belt"; - case Type.FLYING: - return "Sharp Beak"; - case Type.POISON: - return "Poison Barb"; - case Type.GROUND: - return "Soft Sand"; - case Type.ROCK: - return "Hard Stone"; - case Type.BUG: - return "Silver Powder"; - case Type.GHOST: - return "Spell Tag"; - case Type.STEEL: - return "Metal Coat"; - case Type.FIRE: - return "Charcoal"; - case Type.WATER: - return "Mystic Water"; - case Type.GRASS: - return "Miracle Seed"; - case Type.ELECTRIC: - return "Magnet"; - case Type.PSYCHIC: - return "Twisted Spoon"; - case Type.ICE: - return "Never-Melt Ice"; - case Type.DRAGON: - return "Dragon Fang"; - case Type.DARK: - return "Black Glasses"; - case Type.FAIRY: - return "Fairy Feather"; + case Type.NORMAL: + return "Silk Scarf"; + case Type.FIGHTING: + return "Black Belt"; + case Type.FLYING: + return "Sharp Beak"; + case Type.POISON: + return "Poison Barb"; + case Type.GROUND: + return "Soft Sand"; + case Type.ROCK: + return "Hard Stone"; + case Type.BUG: + return "Silver Powder"; + case Type.GHOST: + return "Spell Tag"; + case Type.STEEL: + return "Metal Coat"; + case Type.FIRE: + return "Charcoal"; + case Type.WATER: + return "Mystic Water"; + case Type.GRASS: + return "Miracle Seed"; + case Type.ELECTRIC: + return "Magnet"; + case Type.PSYCHIC: + return "Twisted Spoon"; + case Type.ICE: + return "Never-Melt Ice"; + case Type.DRAGON: + return "Dragon Fang"; + case Type.DARK: + return "Black Glasses"; + case Type.FAIRY: + return "Fairy Feather"; } } @@ -1016,10 +1016,10 @@ class TempStatStageBoosterModifierTypeGenerator extends ModifierTypeGenerator { class SpeciesStatBoosterModifierTypeGenerator extends ModifierTypeGenerator { /** Object comprised of the currently available species-based stat boosting held items */ public static readonly items = { - LIGHT_BALL: { stats: [Stat.ATK, Stat.SPATK], multiplier: 2, species: [Species.PIKACHU] }, - THICK_CLUB: { stats: [Stat.ATK], multiplier: 2, species: [Species.CUBONE, Species.MAROWAK, Species.ALOLA_MAROWAK] }, - METAL_POWDER: { stats: [Stat.DEF], multiplier: 2, species: [Species.DITTO] }, - QUICK_POWDER: { stats: [Stat.SPD], multiplier: 2, species: [Species.DITTO] }, + LIGHT_BALL: { stats: [ Stat.ATK, Stat.SPATK ], multiplier: 2, species: [ Species.PIKACHU ]}, + THICK_CLUB: { stats: [ Stat.ATK ], multiplier: 2, species: [ Species.CUBONE, Species.MAROWAK, Species.ALOLA_MAROWAK ]}, + METAL_POWDER: { stats: [ Stat.DEF ], multiplier: 2, species: [ Species.DITTO ]}, + QUICK_POWDER: { stats: [ Stat.SPD ], multiplier: 2, species: [ Species.DITTO ]}, }; constructor() { @@ -1134,7 +1134,7 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator { return new FormChangeItemModifierType(pregenArgs[0] as FormChangeItem); } - const formChangeItemPool = [...new Set(party.filter(p => pokemonFormChanges.hasOwnProperty(p.species.speciesId)).map(p => { + const formChangeItemPool = [ ...new Set(party.filter(p => pokemonFormChanges.hasOwnProperty(p.species.speciesId)).map(p => { const formChanges = pokemonFormChanges[p.species.speciesId]; let formChangeItemTriggers = formChanges.filter(fc => ((fc.formKey.indexOf(SpeciesFormKey.MEGA) === -1 && fc.formKey.indexOf(SpeciesFormKey.PRIMAL) === -1) || party[0].scene.getModifiers(MegaEvolutionAccessModifier).length) && ((fc.formKey.indexOf(SpeciesFormKey.GIGANTAMAX) === -1 && fc.formKey.indexOf(SpeciesFormKey.ETERNAMAX) === -1) || party[0].scene.getModifiers(GigantamaxAccessModifier).length) @@ -1151,15 +1151,15 @@ class FormChangeItemModifierTypeGenerator extends ModifierTypeGenerator { foundN_SOLAR = false; formChangeItemTriggers.forEach((fc, i) => { switch (fc.item) { - case FormChangeItem.ULTRANECROZIUM_Z: - foundULTRA_Z = true; - break; - case FormChangeItem.N_LUNARIZER: - foundN_LUNA = true; - break; - case FormChangeItem.N_SOLARIZER: - foundN_SOLAR = true; - break; + case FormChangeItem.ULTRANECROZIUM_Z: + foundULTRA_Z = true; + break; + case FormChangeItem.N_LUNARIZER: + foundN_LUNA = true; + break; + case FormChangeItem.N_SOLARIZER: + foundN_SOLAR = true; + break; } }); if (foundULTRA_Z && foundN_LUNA && foundN_SOLAR) { @@ -1509,9 +1509,9 @@ export const modifierTypes = { SOOTHE_BELL: () => new PokemonFriendshipBoosterModifierType("modifierType:ModifierType.SOOTHE_BELL", "soothe_bell"), SCOPE_LENS: () => new PokemonHeldItemModifierType("modifierType:ModifierType.SCOPE_LENS", "scope_lens", (type, args) => new CritBoosterModifier(type, (args[0] as Pokemon).id, 1)), - LEEK: () => new PokemonHeldItemModifierType("modifierType:ModifierType.LEEK", "leek", (type, args) => new SpeciesCritBoosterModifier(type, (args[0] as Pokemon).id, 2, [Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD])), + LEEK: () => new PokemonHeldItemModifierType("modifierType:ModifierType.LEEK", "leek", (type, args) => new SpeciesCritBoosterModifier(type, (args[0] as Pokemon).id, 2, [ Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD ])), - EVIOLITE: () => new PokemonHeldItemModifierType("modifierType:ModifierType.EVIOLITE", "eviolite", (type, args) => new EvolutionStatBoosterModifier(type, (args[0] as Pokemon).id, [Stat.DEF, Stat.SPDEF], 1.5)), + EVIOLITE: () => new PokemonHeldItemModifierType("modifierType:ModifierType.EVIOLITE", "eviolite", (type, args) => new EvolutionStatBoosterModifier(type, (args[0] as Pokemon).id, [ Stat.DEF, Stat.SPDEF ], 1.5)), SOUL_DEW: () => new PokemonHeldItemModifierType("modifierType:ModifierType.SOUL_DEW", "soul_dew", (type, args) => new PokemonNatureWeightModifier(type, (args[0] as Pokemon).id)), @@ -1586,7 +1586,7 @@ export const modifierTypes = { if (pregenArgs) { return new PokemonBaseStatFlatModifierType(pregenArgs[0] as number, pregenArgs[1] as Stat[]); } - return new PokemonBaseStatFlatModifierType(randSeedInt(20), [Stat.HP, Stat.ATK, Stat.DEF]); + return new PokemonBaseStatFlatModifierType(randSeedInt(20), [ Stat.HP, Stat.ATK, Stat.DEF ]); }), MYSTERY_ENCOUNTER_BLACK_SLUDGE: () => new ModifierTypeGenerator((party: Pokemon[], pregenArgs?: any[]) => { if (pregenArgs) { @@ -1736,22 +1736,22 @@ const modifierPool: ModifierPool = { || (p.isFusion() && checkedSpecies.includes(p.getFusionSpeciesForm(true).speciesId)))) ? 12 : 0; }, 12), new WeightedModifierType(modifierTypes.TOXIC_ORB, (party: Pokemon[]) => { - const checkedAbilities = [Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.TOXIC_BOOST, Abilities.POISON_HEAL, Abilities.MAGIC_GUARD]; - const checkedMoves = [Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT]; + const checkedAbilities = [ Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.TOXIC_BOOST, Abilities.POISON_HEAL, Abilities.MAGIC_GUARD ]; + const checkedMoves = [ Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT ]; // If a party member doesn't already have one of these two orbs and has one of the above moves or abilities, the orb can appear return party.some(p => !p.getHeldItems().some(i => i instanceof TurnStatusEffectModifier) && (checkedAbilities.some(a => p.hasAbility(a, false, true)) || p.getMoveset(true).some(m => m && checkedMoves.includes(m.moveId)))) ? 10 : 0; }, 10), new WeightedModifierType(modifierTypes.FLAME_ORB, (party: Pokemon[]) => { - const checkedAbilities = [Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.FLARE_BOOST, Abilities.MAGIC_GUARD]; - const checkedMoves = [Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT]; + const checkedAbilities = [ Abilities.QUICK_FEET, Abilities.GUTS, Abilities.MARVEL_SCALE, Abilities.FLARE_BOOST, Abilities.MAGIC_GUARD ]; + const checkedMoves = [ Moves.FACADE, Moves.TRICK, Moves.FLING, Moves.SWITCHEROO, Moves.PSYCHO_SHIFT ]; // If a party member doesn't already have one of these two orbs and has one of the above moves or abilities, the orb can appear return party.some(p => !p.getHeldItems().some(i => i instanceof TurnStatusEffectModifier) && (checkedAbilities.some(a => p.hasAbility(a, false, true)) || p.getMoveset(true).some(m => m && checkedMoves.includes(m.moveId)))) ? 10 : 0; }, 10), new WeightedModifierType(modifierTypes.WHITE_HERB, (party: Pokemon[]) => { - const checkedAbilities = [Abilities.WEAK_ARMOR, Abilities.CONTRARY, Abilities.MOODY, Abilities.ANGER_SHELL, Abilities.COMPETITIVE, Abilities.DEFIANT]; + const checkedAbilities = [ Abilities.WEAK_ARMOR, Abilities.CONTRARY, Abilities.MOODY, Abilities.ANGER_SHELL, Abilities.COMPETITIVE, Abilities.DEFIANT ]; const weightMultiplier = party.filter( p => !p.getHeldItems().some(i => i instanceof ResetNegativeStatStageModifier && i.stackCount >= i.getMaxHeldItemCount(p)) && (checkedAbilities.some(a => p.hasAbility(a, false, true)) || p.getMoveset(true).some(m => m && selfStatLowerMoves.includes(m.moveId)))).length; @@ -1978,21 +1978,21 @@ let enemyBuffIgnoredPoolIndexes = {}; // eslint-disable-line @typescript-eslint/ export function getModifierPoolForType(poolType: ModifierPoolType): ModifierPool { let pool: ModifierPool; switch (poolType) { - case ModifierPoolType.PLAYER: - pool = modifierPool; - break; - case ModifierPoolType.WILD: - pool = wildModifierPool; - break; - case ModifierPoolType.TRAINER: - pool = trainerModifierPool; - break; - case ModifierPoolType.ENEMY_BUFF: - pool = enemyBuffModifierPool; - break; - case ModifierPoolType.DAILY_STARTER: - pool = dailyStarterModifierPool; - break; + case ModifierPoolType.PLAYER: + pool = modifierPool; + break; + case ModifierPoolType.WILD: + pool = wildModifierPool; + break; + case ModifierPoolType.TRAINER: + pool = trainerModifierPool; + break; + case ModifierPoolType.ENEMY_BUFF: + pool = enemyBuffModifierPool; + break; + case ModifierPoolType.DAILY_STARTER: + pool = dailyStarterModifierPool; + break; } return pool; } @@ -2063,23 +2063,23 @@ export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: Mod console.table(modifierTableData); } switch (poolType) { - case ModifierPoolType.PLAYER: - modifierPoolThresholds = thresholds; - ignoredPoolIndexes = ignoredIndexes; - break; - case ModifierPoolType.WILD: - case ModifierPoolType.TRAINER: - enemyModifierPoolThresholds = thresholds; - enemyIgnoredPoolIndexes = ignoredIndexes; - break; - case ModifierPoolType.ENEMY_BUFF: - enemyBuffModifierPoolThresholds = thresholds; - enemyBuffIgnoredPoolIndexes = ignoredIndexes; - break; - case ModifierPoolType.DAILY_STARTER: - dailyStarterModifierPoolThresholds = thresholds; - ignoredDailyStarterPoolIndexes = ignoredIndexes; - break; + case ModifierPoolType.PLAYER: + modifierPoolThresholds = thresholds; + ignoredPoolIndexes = ignoredIndexes; + break; + case ModifierPoolType.WILD: + case ModifierPoolType.TRAINER: + enemyModifierPoolThresholds = thresholds; + enemyIgnoredPoolIndexes = ignoredIndexes; + break; + case ModifierPoolType.ENEMY_BUFF: + enemyBuffModifierPoolThresholds = thresholds; + enemyBuffIgnoredPoolIndexes = ignoredIndexes; + break; + case ModifierPoolType.DAILY_STARTER: + dailyStarterModifierPoolThresholds = thresholds; + ignoredDailyStarterPoolIndexes = ignoredIndexes; + break; } } @@ -2199,7 +2199,7 @@ export function overridePlayerModifierTypeOptions(options: ModifierTypeOption[], let modifierType: ModifierType | null = modifierFunc(); if (modifierType instanceof ModifierTypeGenerator) { - const pregenArgs = ("type" in override) && (override.type !== null) ? [override.type] : undefined; + const pregenArgs = ("type" in override) && (override.type !== null) ? [ override.type ] : undefined; modifierType = modifierType.generateType(party, pregenArgs); } @@ -2230,7 +2230,8 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base ], [ new ModifierTypeOption(modifierTypes.HYPER_POTION(), 0, baseCost * 0.8), - new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75) + new ModifierTypeOption(modifierTypes.MAX_REVIVE(), 0, baseCost * 2.75), + new ModifierTypeOption(modifierTypes.MEMORY_MUSHROOM(), 0, baseCost * 4) ], [ new ModifierTypeOption(modifierTypes.MAX_POTION(), 0, baseCost * 1.5), @@ -2249,15 +2250,15 @@ export function getPlayerShopModifierTypeOptionsForWave(waveIndex: integer, base export function getEnemyBuffModifierForWave(tier: ModifierTier, enemyModifiers: PersistentModifier[], scene: BattleScene): EnemyPersistentModifier { let tierStackCount: number; switch (tier) { - case ModifierTier.ULTRA: - tierStackCount = 5; - break; - case ModifierTier.GREAT: - tierStackCount = 3; - break; - default: - tierStackCount = 1; - break; + case ModifierTier.ULTRA: + tierStackCount = 5; + break; + case ModifierTier.GREAT: + tierStackCount = 3; + break; + default: + tierStackCount = 1; + break; } const retryCount = 50; @@ -2323,21 +2324,21 @@ function getNewModifierTypeOption(party: Pokemon[], poolType: ModifierPoolType, const pool = getModifierPoolForType(poolType); let thresholds: object; switch (poolType) { - case ModifierPoolType.PLAYER: - thresholds = modifierPoolThresholds; - break; - case ModifierPoolType.WILD: - thresholds = enemyModifierPoolThresholds; - break; - case ModifierPoolType.TRAINER: - thresholds = enemyModifierPoolThresholds; - break; - case ModifierPoolType.ENEMY_BUFF: - thresholds = enemyBuffModifierPoolThresholds; - break; - case ModifierPoolType.DAILY_STARTER: - thresholds = dailyStarterModifierPoolThresholds; - break; + case ModifierPoolType.PLAYER: + thresholds = modifierPoolThresholds; + break; + case ModifierPoolType.WILD: + thresholds = enemyModifierPoolThresholds; + break; + case ModifierPoolType.TRAINER: + thresholds = enemyModifierPoolThresholds; + break; + case ModifierPoolType.ENEMY_BUFF: + thresholds = enemyBuffModifierPoolThresholds; + break; + case ModifierPoolType.DAILY_STARTER: + thresholds = dailyStarterModifierPoolThresholds; + break; } if (tier === undefined) { const tierValue = randSeedInt(1024); diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index a47364355c0..11f16f103a5 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -11,7 +11,7 @@ import Pokemon, { type PlayerPokemon } from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import Overrides from "#app/overrides"; import { EvolutionPhase } from "#app/phases/evolution-phase"; -import { LearnMovePhase } from "#app/phases/learn-move-phase"; +import { LearnMovePhase, LearnMoveType } from "#app/phases/learn-move-phase"; import { LevelUpPhase } from "#app/phases/level-up-phase"; import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; import { achvs } from "#app/system/achv"; @@ -30,6 +30,7 @@ import { StatusEffect } from "#enums/status-effect"; import i18next from "i18next"; import { type DoubleBattleChanceBoosterModifierType, type EvolutionItemModifierType, type FormChangeItemModifierType, type ModifierOverride, type ModifierType, type PokemonBaseStatTotalModifierType, type PokemonExpBoosterModifierType, type PokemonFriendshipBoosterModifierType, type PokemonMoveAccuracyBoosterModifierType, type PokemonMultiHitModifierType, type TerastallizeModifierType, type TmModifierType, getModifierType, ModifierPoolType, ModifierTypeGenerator, modifierTypes, PokemonHeldItemModifierType } from "./modifier-type"; import { Color, ShadowColor } from "#enums/color"; +import { FRIENDSHIP_GAIN_FROM_RARE_CANDY } from "#app/data/balance/starters"; export type ModifierPredicate = (modifier: Modifier) => boolean; @@ -416,7 +417,7 @@ export abstract class LapsingPersistentModifier extends PersistentModifier { } getArgs(): any[] { - return [this.maxBattles, this.battleCount]; + return [ this.maxBattles, this.battleCount ]; } getMaxStackCount(_scene: BattleScene, _forThreshold?: boolean): number { @@ -947,7 +948,7 @@ export class EvoTrackerModifier extends PokemonHeldItemModifier { } getArgs(): any[] { - return super.getArgs().concat([this.species, this.required]); + return super.getArgs().concat([ this.species, this.required ]); } /** @@ -1702,12 +1703,12 @@ export class TurnStatusEffectModifier extends PokemonHeldItemModifier { super(type, pokemonId, stackCount); switch (type.id) { - case "TOXIC_ORB": - this.effect = StatusEffect.TOXIC; - break; - case "FLAME_ORB": - this.effect = StatusEffect.BURN; - break; + case "TOXIC_ORB": + this.effect = StatusEffect.TOXIC; + break; + case "FLAME_ORB": + this.effect = StatusEffect.BURN; + break; } } @@ -1868,7 +1869,7 @@ export class BerryModifier extends PokemonHeldItemModifier { } getMaxHeldItemCount(pokemon: Pokemon): number { - if ([BerryType.LUM, BerryType.LEPPA, BerryType.SITRUS, BerryType.ENIGMA].includes(this.berryType)) { + if ([ BerryType.LUM, BerryType.LEPPA, BerryType.SITRUS, BerryType.ENIGMA ].includes(this.berryType)) { return 2; } return 3; @@ -2221,7 +2222,7 @@ export class PokemonLevelIncrementModifier extends ConsumablePokemonModifier { playerPokemon.levelExp = 0; } - playerPokemon.addFriendship(5); + playerPokemon.addFriendship(FRIENDSHIP_GAIN_FROM_RARE_CANDY); playerPokemon.scene.unshiftPhase(new LevelUpPhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), playerPokemon.level - levelCount.value, playerPokemon.level)); @@ -2243,7 +2244,7 @@ export class TmModifier extends ConsumablePokemonModifier { */ override apply(playerPokemon: PlayerPokemon): boolean { - playerPokemon.scene.unshiftPhase(new LearnMovePhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), this.type.moveId, true)); + playerPokemon.scene.unshiftPhase(new LearnMovePhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), this.type.moveId, LearnMoveType.TM)); return true; } @@ -2263,8 +2264,9 @@ export class RememberMoveModifier extends ConsumablePokemonModifier { * @param playerPokemon The {@linkcode PlayerPokemon} that should remember the move * @returns always `true` */ - override apply(playerPokemon: PlayerPokemon): boolean { - playerPokemon.scene.unshiftPhase(new LearnMovePhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), playerPokemon.getLearnableLevelMoves()[this.levelMoveIndex])); + override apply(playerPokemon: PlayerPokemon, cost?: number): boolean { + + playerPokemon.scene.unshiftPhase(new LearnMovePhase(playerPokemon.scene, playerPokemon.scene.getParty().indexOf(playerPokemon), playerPokemon.getLearnableLevelMoves()[this.levelMoveIndex], LearnMoveType.MEMORY, cost)); return true; } @@ -2690,15 +2692,15 @@ export class PokemonMultiHitModifier extends PokemonHeldItemModifier { count.value *= (this.getStackCount() + 1); switch (this.getStackCount()) { - case 1: - power.value *= 0.4; - break; - case 2: - power.value *= 0.25; - break; - case 3: - power.value *= 0.175; - break; + case 1: + power.value *= 0.4; + break; + case 2: + power.value *= 0.25; + break; + case 3: + power.value *= 0.175; + break; } return true; @@ -3092,11 +3094,12 @@ export abstract class HeldItemTransferModifier extends PokemonHeldItemModifier { * Steals an item from a set of target Pokemon. * This prioritizes high-tier held items when selecting the item to steal. * @param pokemon The {@linkcode Pokemon} holding this item + * @param target The {@linkcode Pokemon} to steal from (optional) * @param _args N/A * @returns `true` if an item was stolen; false otherwise. */ - override apply(pokemon: Pokemon, ..._args: unknown[]): boolean { - const opponents = this.getTargets(pokemon); + override apply(pokemon: Pokemon, target?: Pokemon, ..._args: unknown[]): boolean { + const opponents = this.getTargets(pokemon, target); if (!opponents.length) { return false; @@ -3195,7 +3198,7 @@ export class TurnHeldItemTransferModifier extends HeldItemTransferModifier { * @see {@linkcode HeldItemTransferModifier} */ export class ContactHeldItemTransferChanceModifier extends HeldItemTransferModifier { - private chance: number; + public readonly chance: number; constructor(type: ModifierType, pokemonId: number, chancePercent: number, stackCount?: number) { super(type, pokemonId, stackCount); @@ -3664,7 +3667,7 @@ export function overrideModifiers(scene: BattleScene, isPlayer: boolean = true): let modifierType: ModifierType | null = modifierFunc(); if (modifierType instanceof ModifierTypeGenerator) { - const pregenArgs = ("type" in item) && (item.type !== null) ? [item.type] : undefined; + const pregenArgs = ("type" in item) && (item.type !== null) ? [ item.type ] : undefined; modifierType = modifierType.generateType([], pregenArgs); } @@ -3696,7 +3699,7 @@ export function overrideHeldItems(scene: BattleScene, pokemon: Pokemon, isPlayer } if (!isPlayer) { - scene.clearEnemyHeldItemModifiers(); + scene.clearEnemyHeldItemModifiers(pokemon); } heldItemsOverride.forEach(item => { @@ -3705,7 +3708,7 @@ export function overrideHeldItems(scene: BattleScene, pokemon: Pokemon, isPlayer const qty = item.count || 1; if (modifierType instanceof ModifierTypeGenerator) { - const pregenArgs = ("type" in item) && (item.type !== null) ? [item.type] : undefined; + const pregenArgs = ("type" in item) && (item.type !== null) ? [ item.type ] : undefined; modifierType = modifierType.generateType([], pregenArgs); } diff --git a/src/overrides.ts b/src/overrides.ts index 852961db8d7..211d430a835 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -100,6 +100,14 @@ class DefaultOverrides { * @example SPECIES_OVERRIDE = Species.Bulbasaur; */ readonly STARTER_SPECIES_OVERRIDE: Species | number = 0; + /** + * This will force your starter to be a random fusion + */ + readonly STARTER_FUSION_OVERRIDE: boolean = false; + /** + * This will override the species of the fusion + */ + readonly STARTER_FUSION_SPECIES_OVERRIDE: Species | integer = 0; readonly ABILITY_OVERRIDE: Abilities = Abilities.NONE; readonly PASSIVE_ABILITY_OVERRIDE: Abilities = Abilities.NONE; readonly STATUS_OVERRIDE: StatusEffect = StatusEffect.NONE; @@ -112,6 +120,14 @@ class DefaultOverrides { // OPPONENT / ENEMY OVERRIDES // -------------------------- readonly OPP_SPECIES_OVERRIDE: Species | number = 0; + /** + * This will make all opponents fused Pokemon + */ + readonly OPP_FUSION_OVERRIDE: boolean = false; + /** + * This will override the species of the fusion only when the opponent is already a fusion + */ + readonly OPP_FUSION_SPECIES_OVERRIDE: Species | integer = 0; readonly OPP_LEVEL_OVERRIDE: number = 0; readonly OPP_ABILITY_OVERRIDE: Abilities = Abilities.NONE; readonly OPP_PASSIVE_ABILITY_OVERRIDE: Abilities = Abilities.NONE; @@ -140,6 +156,7 @@ class DefaultOverrides { readonly EGG_VARIANT_OVERRIDE: VariantTier | null = null; readonly EGG_FREE_GACHA_PULLS_OVERRIDE: boolean = false; readonly EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0; + readonly UNLIMITED_EGG_COUNT_OVERRIDE: boolean = false; // ------------------------- // MYSTERY ENCOUNTER OVERRIDES diff --git a/src/phase.ts b/src/phase.ts index 02939757112..5cf91f2c478 100644 --- a/src/phase.ts +++ b/src/phase.ts @@ -8,7 +8,6 @@ export class Phase { } start() { - console.log(`%cStart Phase ${this.constructor.name}`, "color:green;"); if (this.scene.abilityBar.shown) { this.scene.abilityBar.resetAutoHideTimer(); } diff --git a/src/phases/attempt-capture-phase.ts b/src/phases/attempt-capture-phase.ts index 53723526c14..3e46fc792f0 100644 --- a/src/phases/attempt-capture-phase.ts +++ b/src/phases/attempt-capture-phase.ts @@ -248,7 +248,7 @@ export class AttemptCapturePhase extends PokemonPhase { } }); }; - Promise.all([pokemon.hideInfo(), this.scene.gameData.setPokemonCaught(pokemon)]).then(() => { + Promise.all([ pokemon.hideInfo(), this.scene.gameData.setPokemonCaught(pokemon) ]).then(() => { if (this.scene.getParty().length === 6) { const promptRelease = () => { this.scene.ui.showText(i18next.t("battle:partyFull", { pokemonName: pokemon.getNameToRender() }), null, () => { diff --git a/src/phases/attempt-run-phase.ts b/src/phases/attempt-run-phase.ts index 46d68f6005a..e0dd7fa72fd 100644 --- a/src/phases/attempt-run-phase.ts +++ b/src/phases/attempt-run-phase.ts @@ -33,7 +33,7 @@ export class AttemptRunPhase extends PokemonPhase { this.scene.queueMessage(i18next.t("battle:runAwaySuccess"), null, true, 500); this.scene.tweens.add({ - targets: [this.scene.arenaEnemy, enemyField].flat(), + targets: [ this.scene.arenaEnemy, enemyField ].flat(), alpha: 0, duration: 250, ease: "Sine.easeIn", diff --git a/src/phases/battle-phase.ts b/src/phases/battle-phase.ts index b51e19bdf0e..11807fdc714 100644 --- a/src/phases/battle-phase.ts +++ b/src/phases/battle-phase.ts @@ -12,7 +12,7 @@ export class BattlePhase extends Phase { const tintSprites = this.scene.currentBattle.trainer?.getTintSprites()!; // TODO: is this bang correct? for (let i = 0; i < sprites.length; i++) { const visible = !trainerSlot || !i === (trainerSlot === TrainerSlot.TRAINER) || sprites.length < 2; - [sprites[i], tintSprites[i]].map(sprite => { + [ sprites[i], tintSprites[i] ].map(sprite => { if (visible) { sprite.x = trainerSlot || sprites.length < 2 ? 0 : i ? 16 : -16; } diff --git a/src/phases/check-status-effect-phase.ts b/src/phases/check-status-effect-phase.ts new file mode 100644 index 00000000000..44918b54966 --- /dev/null +++ b/src/phases/check-status-effect-phase.ts @@ -0,0 +1,23 @@ +import { PostTurnStatusEffectPhase } from "#app/phases/post-turn-status-effect-phase"; +import { Phase } from "#app/phase"; +import { BattlerIndex } from "#app/battle"; +import BattleScene from "#app/battle-scene"; + +export class CheckStatusEffectPhase extends Phase { + private order : BattlerIndex[]; + constructor(scene : BattleScene, order : BattlerIndex[]) { + super(scene); + this.scene = scene; + this.order = order; + } + + start() { + const field = this.scene.getField(); + for (const o of this.order) { + if (field[o].status && field[o].status.isPostTurn()) { + this.scene.unshiftPhase(new PostTurnStatusEffectPhase(this.scene, o)); + } + } + this.end(); + } +} diff --git a/src/phases/command-phase.ts b/src/phases/command-phase.ts index 5e5031c1d06..e6f2eb69ff3 100644 --- a/src/phases/command-phase.ts +++ b/src/phases/command-phase.ts @@ -84,170 +84,170 @@ export class CommandPhase extends FieldPhase { let success: boolean; switch (command) { - case Command.FIGHT: - let useStruggle = false; - if (cursor === -1 || + case Command.FIGHT: + let useStruggle = false; + if (cursor === -1 || playerPokemon.trySelectMove(cursor, args[0] as boolean) || (useStruggle = cursor > -1 && !playerPokemon.getMoveset().filter(m => m?.isUsable(playerPokemon)).length)) { - const moveId = !useStruggle ? cursor > -1 ? playerPokemon.getMoveset()[cursor]!.moveId : Moves.NONE : Moves.STRUGGLE; // TODO: is the bang correct? - const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: { move: moveId, targets: [], ignorePP: args[0] }, args: args }; - const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, moveId) : args[2]; - if (!moveId) { - turnCommand.targets = [this.fieldIndex]; - } - console.log(moveTargets, getPokemonNameWithAffix(playerPokemon)); - if (moveTargets.targets.length > 1 && moveTargets.multiple) { - this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); - } - if (moveTargets.targets.length <= 1 || moveTargets.multiple) { + const moveId = !useStruggle ? cursor > -1 ? playerPokemon.getMoveset()[cursor]!.moveId : Moves.NONE : Moves.STRUGGLE; // TODO: is the bang correct? + const turnCommand: TurnCommand = { command: Command.FIGHT, cursor: cursor, move: { move: moveId, targets: [], ignorePP: args[0] }, args: args }; + const moveTargets: MoveTargetSet = args.length < 3 ? getMoveTargets(playerPokemon, moveId) : args[2]; + if (!moveId) { + turnCommand.targets = [ this.fieldIndex ]; + } + console.log(moveTargets, getPokemonNameWithAffix(playerPokemon)); + if (moveTargets.targets.length > 1 && moveTargets.multiple) { + this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); + } + if (moveTargets.targets.length <= 1 || moveTargets.multiple) { turnCommand.move!.targets = moveTargets.targets; //TODO: is the bang correct here? - } else if (playerPokemon.getTag(BattlerTagType.CHARGING) && playerPokemon.getMoveQueue().length >= 1) { + } else if (playerPokemon.getTag(BattlerTagType.CHARGING) && playerPokemon.getMoveQueue().length >= 1) { turnCommand.move!.targets = playerPokemon.getMoveQueue()[0].targets; //TODO: is the bang correct here? - } else { - this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); - } - this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand; - success = true; - } else if (cursor < playerPokemon.getMoveset().length) { - const move = playerPokemon.getMoveset()[cursor]!; //TODO: is this bang correct? - this.scene.ui.setMode(Mode.MESSAGE); + } else { + this.scene.unshiftPhase(new SelectTargetPhase(this.scene, this.fieldIndex)); + } + this.scene.currentBattle.turnCommands[this.fieldIndex] = turnCommand; + success = true; + } else if (cursor < playerPokemon.getMoveset().length) { + const move = playerPokemon.getMoveset()[cursor]!; //TODO: is this bang correct? + this.scene.ui.setMode(Mode.MESSAGE); - // Decides between a Disabled, Not Implemented, or No PP translation message - const errorMessage = - playerPokemon.isMoveRestricted(move.moveId) - ? playerPokemon.getRestrictingTag(move.moveId)!.selectionDeniedText(playerPokemon, move.moveId) + // Decides between a Disabled, Not Implemented, or No PP translation message + const errorMessage = + playerPokemon.isMoveRestricted(move.moveId, playerPokemon) + ? playerPokemon.getRestrictingTag(move.moveId, playerPokemon)!.selectionDeniedText(playerPokemon, move.moveId) : move.getName().endsWith(" (N)") ? "battle:moveNotImplemented" : "battle:moveNoPP"; - const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator + const moveName = move.getName().replace(" (N)", ""); // Trims off the indicator - this.scene.ui.showText(i18next.t(errorMessage, { moveName: moveName }), null, () => { - this.scene.ui.clearText(); - this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex); - }, null, true); - } - break; - case Command.BALL: - const notInDex = (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarterCosts).length - 1); - if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || this.scene.gameMode.isFreshStartChallenge() || notInDex )) { - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t("battle:noPokeballForce"), null, () => { - this.scene.ui.showText("", 0); - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - }, null, true); - } else if (this.scene.currentBattle.battleType === BattleType.TRAINER) { - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t("battle:noPokeballTrainer"), null, () => { - this.scene.ui.showText("", 0); - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - }, null, true); - } else if (this.scene.currentBattle.isBattleMysteryEncounter() && !this.scene.currentBattle.mysteryEncounter!.catchAllowed) { - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t("battle:noPokeballMysteryEncounter"), null, () => { - this.scene.ui.showText("", 0); - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - }, null, true); - } else { - const targets = this.scene.getEnemyField().filter(p => p.isActive(true)).map(p => p.getBattlerIndex()); - if (targets.length > 1) { + this.scene.ui.showText(i18next.t(errorMessage, { moveName: moveName }), null, () => { + this.scene.ui.clearText(); + this.scene.ui.setMode(Mode.FIGHT, this.fieldIndex); + }, null, true); + } + break; + case Command.BALL: + const notInDex = (this.scene.getEnemyField().filter(p => p.isActive(true)).some(p => !p.scene.gameData.dexData[p.species.speciesId].caughtAttr) && this.scene.gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarterCosts).length - 1); + if (this.scene.arena.biomeType === Biome.END && (!this.scene.gameMode.isClassic || this.scene.gameMode.isFreshStartChallenge() || notInDex )) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t("battle:noPokeballMulti"), null, () => { + this.scene.ui.showText(i18next.t("battle:noPokeballForce"), null, () => { this.scene.ui.showText("", 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); - } else if (cursor < 5) { - const targetPokemon = this.scene.getEnemyField().find(p => p.isActive(true)); - if (targetPokemon?.isBoss() && targetPokemon?.bossSegmentIndex >= 1 && !targetPokemon?.hasAbility(Abilities.WONDER_GUARD, false, true) && cursor < PokeballType.MASTER_BALL) { + } else if (this.scene.currentBattle.battleType === BattleType.TRAINER) { + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); + this.scene.ui.setMode(Mode.MESSAGE); + this.scene.ui.showText(i18next.t("battle:noPokeballTrainer"), null, () => { + this.scene.ui.showText("", 0); + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); + }, null, true); + } else if (this.scene.currentBattle.isBattleMysteryEncounter() && !this.scene.currentBattle.mysteryEncounter!.catchAllowed) { + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); + this.scene.ui.setMode(Mode.MESSAGE); + this.scene.ui.showText(i18next.t("battle:noPokeballMysteryEncounter"), null, () => { + this.scene.ui.showText("", 0); + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); + }, null, true); + } else { + const targets = this.scene.getEnemyField().filter(p => p.isActive(true)).map(p => p.getBattlerIndex()); + if (targets.length > 1) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t("battle:noPokeballStrong"), null, () => { + this.scene.ui.showText(i18next.t("battle:noPokeballMulti"), null, () => { this.scene.ui.showText("", 0); this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); - } else { - this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: Command.BALL, cursor: cursor }; + } else if (cursor < 5) { + const targetPokemon = this.scene.getEnemyField().find(p => p.isActive(true)); + if (targetPokemon?.isBoss() && targetPokemon?.bossSegmentIndex >= 1 && !targetPokemon?.hasAbility(Abilities.WONDER_GUARD, false, true) && cursor < PokeballType.MASTER_BALL) { + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); + this.scene.ui.setMode(Mode.MESSAGE); + this.scene.ui.showText(i18next.t("battle:noPokeballStrong"), null, () => { + this.scene.ui.showText("", 0); + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); + }, null, true); + } else { + this.scene.currentBattle.turnCommands[this.fieldIndex] = { command: Command.BALL, cursor: cursor }; this.scene.currentBattle.turnCommands[this.fieldIndex]!.targets = targets; if (this.fieldIndex) { this.scene.currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true; } success = true; + } } } - } - break; - case Command.POKEMON: - case Command.RUN: - const isSwitch = command === Command.POKEMON; - const { currentBattle, arena } = this.scene; - const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed; - if (!isSwitch && (arena.biomeType === Biome.END || (!isNullOrUndefined(mysteryEncounterFleeAllowed) && !mysteryEncounterFleeAllowed))) { - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t("battle:noEscapeForce"), null, () => { - this.scene.ui.showText("", 0); + break; + case Command.POKEMON: + case Command.RUN: + const isSwitch = command === Command.POKEMON; + const { currentBattle, arena } = this.scene; + const mysteryEncounterFleeAllowed = currentBattle.mysteryEncounter?.fleeAllowed; + if (!isSwitch && (arena.biomeType === Biome.END || (!isNullOrUndefined(mysteryEncounterFleeAllowed) && !mysteryEncounterFleeAllowed))) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - }, null, true); - } else if (!isSwitch && (currentBattle.battleType === BattleType.TRAINER || currentBattle.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE)) { - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - this.scene.ui.setMode(Mode.MESSAGE); - this.scene.ui.showText(i18next.t("battle:noEscapeTrainer"), null, () => { - this.scene.ui.showText("", 0); - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - }, null, true); - } else { - const batonPass = isSwitch && args[0] as boolean; - const trappedAbMessages: string[] = []; - if (batonPass || !playerPokemon.isTrapped(trappedAbMessages)) { - currentBattle.turnCommands[this.fieldIndex] = isSwitch - ? { command: Command.POKEMON, cursor: cursor, args: args } - : { command: Command.RUN }; - success = true; - if (!isSwitch && this.fieldIndex) { - currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true; - } - } else if (trappedAbMessages.length > 0) { - if (!isSwitch) { - this.scene.ui.setMode(Mode.MESSAGE); - } - this.scene.ui.showText(trappedAbMessages[0], null, () => { + this.scene.ui.setMode(Mode.MESSAGE); + this.scene.ui.showText(i18next.t("battle:noEscapeForce"), null, () => { this.scene.ui.showText("", 0); - if (!isSwitch) { - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - } + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); + }, null, true); + } else if (!isSwitch && (currentBattle.battleType === BattleType.TRAINER || currentBattle.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE)) { + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); + this.scene.ui.setMode(Mode.MESSAGE); + this.scene.ui.showText(i18next.t("battle:noEscapeTrainer"), null, () => { + this.scene.ui.showText("", 0); + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); }, null, true); } else { - const trapTag = playerPokemon.getTag(TrappedTag); - - // trapTag should be defined at this point, but just in case... - if (!trapTag) { + const batonPass = isSwitch && args[0] as boolean; + const trappedAbMessages: string[] = []; + if (batonPass || !playerPokemon.isTrapped(trappedAbMessages)) { currentBattle.turnCommands[this.fieldIndex] = isSwitch ? { command: Command.POKEMON, cursor: cursor, args: args } : { command: Command.RUN }; - break; - } - - if (!isSwitch) { - this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); - this.scene.ui.setMode(Mode.MESSAGE); - } - this.scene.ui.showText( - i18next.t("battle:noEscapePokemon", { - pokemonName: trapTag.sourceId && this.scene.getPokemonById(trapTag.sourceId) ? getPokemonNameWithAffix(this.scene.getPokemonById(trapTag.sourceId)!) : "", - moveName: trapTag.getMoveName(), - escapeVerb: isSwitch ? i18next.t("battle:escapeVerbSwitch") : i18next.t("battle:escapeVerbFlee") - }), - null, - () => { + success = true; + if (!isSwitch && this.fieldIndex) { + currentBattle.turnCommands[this.fieldIndex - 1]!.skip = true; + } + } else if (trappedAbMessages.length > 0) { + if (!isSwitch) { + this.scene.ui.setMode(Mode.MESSAGE); + } + this.scene.ui.showText(trappedAbMessages[0], null, () => { this.scene.ui.showText("", 0); if (!isSwitch) { this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); } }, null, true); + } else { + const trapTag = playerPokemon.getTag(TrappedTag); + + // trapTag should be defined at this point, but just in case... + if (!trapTag) { + currentBattle.turnCommands[this.fieldIndex] = isSwitch + ? { command: Command.POKEMON, cursor: cursor, args: args } + : { command: Command.RUN }; + break; + } + + if (!isSwitch) { + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); + this.scene.ui.setMode(Mode.MESSAGE); + } + this.scene.ui.showText( + i18next.t("battle:noEscapePokemon", { + pokemonName: trapTag.sourceId && this.scene.getPokemonById(trapTag.sourceId) ? getPokemonNameWithAffix(this.scene.getPokemonById(trapTag.sourceId)!) : "", + moveName: trapTag.getMoveName(), + escapeVerb: isSwitch ? i18next.t("battle:escapeVerbSwitch") : i18next.t("battle:escapeVerbFlee") + }), + null, + () => { + this.scene.ui.showText("", 0); + if (!isSwitch) { + this.scene.ui.setMode(Mode.COMMAND, this.fieldIndex); + } + }, null, true); + } } - } - break; + break; } if (success!) { // TODO: is the bang correct? diff --git a/src/phases/damage-phase.ts b/src/phases/damage-phase.ts index 66b11512729..44e3dfd4182 100644 --- a/src/phases/damage-phase.ts +++ b/src/phases/damage-phase.ts @@ -41,16 +41,16 @@ export class DamagePhase extends PokemonPhase { applyDamage() { switch (this.damageResult) { - case HitResult.EFFECTIVE: - this.scene.playSound("se/hit"); - break; - case HitResult.SUPER_EFFECTIVE: - case HitResult.ONE_HIT_KO: - this.scene.playSound("se/hit_strong"); - break; - case HitResult.NOT_VERY_EFFECTIVE: - this.scene.playSound("se/hit_weak"); - break; + case HitResult.EFFECTIVE: + this.scene.playSound("se/hit"); + break; + case HitResult.SUPER_EFFECTIVE: + case HitResult.ONE_HIT_KO: + this.scene.playSound("se/hit_strong"); + break; + case HitResult.NOT_VERY_EFFECTIVE: + this.scene.playSound("se/hit_weak"); + break; } if (this.amount) { diff --git a/src/phases/egg-lapse-phase.ts b/src/phases/egg-lapse-phase.ts index c251819f331..4c57be09b79 100644 --- a/src/phases/egg-lapse-phase.ts +++ b/src/phases/egg-lapse-phase.ts @@ -28,12 +28,12 @@ export class EggLapsePhase extends Phase { return Overrides.EGG_IMMEDIATE_HATCH_OVERRIDE ? true : --egg.hatchWaves < 1; }); const eggsToHatchCount: number = eggsToHatch.length; - this.eggHatchData= []; + this.eggHatchData = []; if (eggsToHatchCount > 0) { if (eggsToHatchCount >= this.minEggsToSkip && this.scene.eggSkipPreference === 1) { this.scene.ui.showText(i18next.t("battle:eggHatching"), 0, () => { - // show prompt for skip + // show prompt for skip, blocking inputs for 1 second this.scene.ui.showText(i18next.t("battle:eggSkipPrompt"), 0); this.scene.ui.setModeWithoutClear(Mode.CONFIRM, () => { this.hatchEggsSkipped(eggsToHatch); @@ -41,7 +41,8 @@ export class EggLapsePhase extends Phase { }, () => { this.hatchEggsRegular(eggsToHatch); this.end(); - } + }, + null, null, null, 1000, true ); }, 100, true); } else if (eggsToHatchCount >= this.minEggsToSkip && this.scene.eggSkipPreference === 2) { diff --git a/src/phases/egg-summary-phase.ts b/src/phases/egg-summary-phase.ts index 75c6939daf1..b673eb4887b 100644 --- a/src/phases/egg-summary-phase.ts +++ b/src/phases/egg-summary-phase.ts @@ -1,7 +1,6 @@ import BattleScene from "#app/battle-scene"; import { Phase } from "#app/phase"; import { Mode } from "#app/ui/ui"; -import EggHatchSceneHandler from "#app/ui/egg-hatch-scene-handler"; import { EggHatchData } from "#app/data/egg-hatch-data"; /** @@ -11,7 +10,6 @@ import { EggHatchData } from "#app/data/egg-hatch-data"; */ export class EggSummaryPhase extends Phase { private eggHatchData: EggHatchData[]; - private eggHatchHandler: EggHatchSceneHandler; constructor(scene: BattleScene, eggHatchData: EggHatchData[]) { super(scene); @@ -26,7 +24,6 @@ export class EggSummaryPhase extends Phase { if (i >= this.eggHatchData.length) { this.scene.ui.setModeForceTransition(Mode.EGG_HATCH_SUMMARY, this.eggHatchData).then(() => { this.scene.fadeOutBgm(undefined, false); - this.eggHatchHandler = this.scene.ui.getHandler() as EggHatchSceneHandler; }); } else { diff --git a/src/phases/encounter-phase.ts b/src/phases/encounter-phase.ts index 798ee3dca3c..84f07f3ee94 100644 --- a/src/phases/encounter-phase.ts +++ b/src/phases/encounter-phase.ts @@ -259,7 +259,7 @@ export class EncounterPhase extends BattlePhase { const enemyField = this.scene.getEnemyField(); this.scene.tweens.add({ - targets: [this.scene.arenaEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.arenaPlayer, this.scene.trainer].flat(), + targets: [ this.scene.arenaEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.arenaPlayer, this.scene.trainer ].flat(), x: (_target, _key, value, fieldIndex: integer) => fieldIndex < 2 + (enemyField.length) ? value + 300 : value - 300, duration: 2000, onComplete: () => { @@ -287,7 +287,7 @@ export class EncounterPhase extends BattlePhase { const enemyField = this.scene.getEnemyField(); if (this.scene.currentBattle.battleSpec === BattleSpec.FINAL_BOSS) { - return i18next.t("battle:bossAppeared", { bossName: getPokemonNameWithAffix(enemyField[0])}); + return i18next.t("battle:bossAppeared", { bossName: getPokemonNameWithAffix(enemyField[0]) }); } if (this.scene.currentBattle.battleType === BattleType.TRAINER) { @@ -436,7 +436,7 @@ export class EncounterPhase extends BattlePhase { } }); - if (![BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(this.scene.currentBattle.battleType)) { + if (![ BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER ].includes(this.scene.currentBattle.battleType)) { enemyField.map(p => this.scene.pushConditionalPhase(new PostSummonPhase(this.scene, p.getBattlerIndex()), () => { // if there is not a player party, we can't continue if (!this.scene.getParty()?.length) { @@ -494,31 +494,31 @@ export class EncounterPhase extends BattlePhase { tryOverrideForBattleSpec(): boolean { switch (this.scene.currentBattle.battleSpec) { - case BattleSpec.FINAL_BOSS: - const enemy = this.scene.getEnemyPokemon(); - this.scene.ui.showText(this.getEncounterMessage(), null, () => { - const localizationKey = "battleSpecDialogue:encounter"; - if (this.scene.ui.shouldSkipDialogue(localizationKey)) { + case BattleSpec.FINAL_BOSS: + const enemy = this.scene.getEnemyPokemon(); + this.scene.ui.showText(this.getEncounterMessage(), null, () => { + const localizationKey = "battleSpecDialogue:encounter"; + if (this.scene.ui.shouldSkipDialogue(localizationKey)) { // Logging mirrors logging found in dialogue-ui-handler - console.log(`Dialogue ${localizationKey} skipped`); - this.doEncounterCommon(false); - } else { - const count = 5643853 + this.scene.gameData.gameStats.classicSessionsPlayed; - // The line below checks if an English ordinal is necessary or not based on whether an entry for encounterLocalizationKey exists in the language or not. - const ordinalUsed = !i18next.exists(localizationKey, {fallbackLng: []}) || i18next.resolvedLanguage === "en" ? i18next.t("battleSpecDialogue:key", { count: count, ordinal: true }) : ""; - const cycleCount = count.toLocaleString() + ordinalUsed; - const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; - const genderStr = PlayerGender[genderIndex].toLowerCase(); - const encounterDialogue = i18next.t(localizationKey, { context: genderStr, cycleCount: cycleCount }); - if (!this.scene.gameData.getSeenDialogues()[localizationKey]) { - this.scene.gameData.saveSeenDialogue(localizationKey); - } - this.scene.ui.showDialogue(encounterDialogue, enemy?.species.name, null, () => { + console.log(`Dialogue ${localizationKey} skipped`); this.doEncounterCommon(false); - }); - } - }, 1500, true); - return true; + } else { + const count = 5643853 + this.scene.gameData.gameStats.classicSessionsPlayed; + // The line below checks if an English ordinal is necessary or not based on whether an entry for encounterLocalizationKey exists in the language or not. + const ordinalUsed = !i18next.exists(localizationKey, { fallbackLng: []}) || i18next.resolvedLanguage === "en" ? i18next.t("battleSpecDialogue:key", { count: count, ordinal: true }) : ""; + const cycleCount = count.toLocaleString() + ordinalUsed; + const genderIndex = this.scene.gameData.gender ?? PlayerGender.UNSET; + const genderStr = PlayerGender[genderIndex].toLowerCase(); + const encounterDialogue = i18next.t(localizationKey, { context: genderStr, cycleCount: cycleCount }); + if (!this.scene.gameData.getSeenDialogues()[localizationKey]) { + this.scene.gameData.saveSeenDialogue(localizationKey); + } + this.scene.ui.showDialogue(encounterDialogue, enemy?.species.name, null, () => { + this.doEncounterCommon(false); + }); + } + }, 1500, true); + return true; } return false; } diff --git a/src/phases/enemy-command-phase.ts b/src/phases/enemy-command-phase.ts index b4503a7b059..3647a237ef1 100644 --- a/src/phases/enemy-command-phase.ts +++ b/src/phases/enemy-command-phase.ts @@ -61,7 +61,7 @@ export class EnemyCommandPhase extends FieldPhase { const index = trainer.getNextSummonIndex(enemyPokemon.trainerSlot, partyMemberScores); battle.turnCommands[this.fieldIndex + BattlerIndex.ENEMY] = - { command: Command.POKEMON, cursor: index, args: [false], skip: this.skipTurn }; + { command: Command.POKEMON, cursor: index, args: [ false ], skip: this.skipTurn }; battle.enemySwitchCounter++; diff --git a/src/phases/faint-phase.ts b/src/phases/faint-phase.ts index ba25225f6e0..eee1fd52938 100644 --- a/src/phases/faint-phase.ts +++ b/src/phases/faint-phase.ts @@ -1,12 +1,12 @@ import BattleScene from "#app/battle-scene"; import { BattlerIndex, BattleType } from "#app/battle"; import { applyPostFaintAbAttrs, PostFaintAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr } from "#app/data/ability"; -import { BattlerTagLapseType } from "#app/data/battler-tags"; +import { BattlerTagLapseType, DestinyBondTag } from "#app/data/battler-tags"; import { battleSpecDialogue } from "#app/data/dialogue"; import { allMoves, PostVictoryStatStageChangeAttr } from "#app/data/move"; import { BattleSpec } from "#app/enums/battle-spec"; import { StatusEffect } from "#app/enums/status-effect"; -import { PokemonMove, EnemyPokemon, PlayerPokemon, HitResult } from "#app/field/pokemon"; +import Pokemon, { PokemonMove, EnemyPokemon, PlayerPokemon, HitResult } from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import { PokemonInstantReviveModifier } from "#app/modifier/modifier"; import i18next from "i18next"; @@ -19,19 +19,40 @@ import { SwitchPhase } from "./switch-phase"; import { VictoryPhase } from "./victory-phase"; import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; import { SwitchType } from "#enums/switch-type"; +import { isNullOrUndefined } from "#app/utils"; +import { FRIENDSHIP_LOSS_FROM_FAINT } from "#app/data/balance/starters"; export class FaintPhase extends PokemonPhase { + /** + * Whether or not enduring (for this phase's purposes, Reviver Seed) should be prevented + */ private preventEndure: boolean; - constructor(scene: BattleScene, battlerIndex: BattlerIndex, preventEndure?: boolean) { + /** + * Destiny Bond tag belonging to the currently fainting Pokemon, if applicable + */ + private destinyTag?: DestinyBondTag; + + /** + * The source Pokemon that dealt fatal damage and should get KO'd by Destiny Bond, if applicable + */ + private source?: Pokemon; + + constructor(scene: BattleScene, battlerIndex: BattlerIndex, preventEndure: boolean = false, destinyTag?: DestinyBondTag, source?: Pokemon) { super(scene, battlerIndex); - this.preventEndure = preventEndure!; // TODO: is this bang correct? + this.preventEndure = preventEndure; + this.destinyTag = destinyTag; + this.source = source; } start() { super.start(); + if (!isNullOrUndefined(this.destinyTag) && !isNullOrUndefined(this.source)) { + this.destinyTag.lapse(this.source, BattlerTagLapseType.CUSTOM); + } + if (!this.preventEndure) { const instantReviveModifier = this.scene.applyModifier(PokemonInstantReviveModifier, this.player, this.getPokemon()) as PokemonInstantReviveModifier; @@ -111,7 +132,7 @@ export class FaintPhase extends PokemonPhase { } } else { this.scene.unshiftPhase(new VictoryPhase(this.scene, this.battlerIndex)); - if ([BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(this.scene.currentBattle.battleType)) { + if ([ BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER ].includes(this.scene.currentBattle.battleType)) { const hasReservePartyMember = !!this.scene.getEnemyParty().filter(p => p.isActive() && !p.isOnField() && p.trainerSlot === (pokemon as EnemyPokemon).trainerSlot).length; if (hasReservePartyMember) { this.scene.pushPhase(new SwitchSummonPhase(this.scene, SwitchType.SWITCH, this.fieldIndex, -1, false, false)); @@ -127,7 +148,7 @@ export class FaintPhase extends PokemonPhase { pokemon.faintCry(() => { if (pokemon instanceof PlayerPokemon) { - pokemon.addFriendship(-10); + pokemon.addFriendship(-FRIENDSHIP_LOSS_FROM_FAINT); } pokemon.hideInfo(); this.scene.playSound("se/faint"); @@ -158,19 +179,19 @@ export class FaintPhase extends PokemonPhase { tryOverrideForBattleSpec(): boolean { switch (this.scene.currentBattle.battleSpec) { - case BattleSpec.FINAL_BOSS: - if (!this.player) { - const enemy = this.getPokemon(); - if (enemy.formIndex) { - this.scene.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].secondStageWin, enemy.species.name, null, () => this.doFaint()); - } else { + case BattleSpec.FINAL_BOSS: + if (!this.player) { + const enemy = this.getPokemon(); + if (enemy.formIndex) { + this.scene.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].secondStageWin, enemy.species.name, null, () => this.doFaint()); + } else { // Final boss' HP threshold has been bypassed; cancel faint and force check for 2nd phase - enemy.hp++; - this.scene.unshiftPhase(new DamagePhase(this.scene, enemy.getBattlerIndex(), 0, HitResult.OTHER)); - this.end(); + enemy.hp++; + this.scene.unshiftPhase(new DamagePhase(this.scene, enemy.getBattlerIndex(), 0, HitResult.OTHER)); + this.end(); + } + return true; } - return true; - } } return false; diff --git a/src/phases/learn-move-phase.ts b/src/phases/learn-move-phase.ts index 5b4b16f3785..eb7cfbb65ef 100644 --- a/src/phases/learn-move-phase.ts +++ b/src/phases/learn-move-phase.ts @@ -2,24 +2,37 @@ import BattleScene from "#app/battle-scene"; import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims"; import Move, { allMoves } from "#app/data/move"; import { SpeciesFormChangeMoveLearnedTrigger } from "#app/data/pokemon-forms"; -import { Moves } from "#app/enums/moves"; +import { Moves } from "#enums/moves"; import { getPokemonNameWithAffix } from "#app/messages"; +import Overrides from "#app/overrides"; import EvolutionSceneHandler from "#app/ui/evolution-scene-handler"; import { SummaryUiMode } from "#app/ui/summary-ui-handler"; import { Mode } from "#app/ui/ui"; import i18next from "i18next"; -import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-phase"; +import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase"; import Pokemon from "#app/field/pokemon"; +import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; + +export enum LearnMoveType { + /** For learning a move via level-up, evolution, or other non-item-based event */ + LEARN_MOVE, + /** For learning a move via Memory Mushroom */ + MEMORY, + /** For learning a move via TM */ + TM +} export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { private moveId: Moves; private messageMode: Mode; - private fromTM: boolean; + private learnMoveType; + private cost: number; - constructor(scene: BattleScene, partyMemberIndex: integer, moveId: Moves, fromTM?: boolean) { + constructor(scene: BattleScene, partyMemberIndex: integer, moveId: Moves, learnMoveType: LearnMoveType = LearnMoveType.LEARN_MOVE, cost: number = -1) { super(scene, partyMemberIndex); this.moveId = moveId; - this.fromTM = fromTM ?? false; + this.learnMoveType = learnMoveType; + this.cost = cost; } start() { @@ -59,7 +72,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { const learnMovePrompt = i18next.t("battle:learnMovePrompt", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }); const moveLimitReached = i18next.t("battle:learnMoveLimitReached", { pokemonName: getPokemonNameWithAffix(pokemon) }); const shouldReplaceQ = i18next.t("battle:learnMoveReplaceQuestion", { moveName: move.name }); - const preQText = [learnMovePrompt, moveLimitReached].join("$"); + const preQText = [ learnMovePrompt, moveLimitReached ].join("$"); await this.scene.ui.showTextPromise(preQText); await this.scene.ui.showTextPromise(shouldReplaceQ, undefined, false); await this.scene.ui.setModeWithoutClear(Mode.CONFIRM, @@ -91,7 +104,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { return; } const forgetSuccessText = i18next.t("battle:learnMoveForgetSuccess", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: pokemon.moveset[moveIndex]!.getName() }); - const fullText = [i18next.t("battle:countdownPoof"), forgetSuccessText, i18next.t("battle:learnMoveAnd")].join("$"); + const fullText = [ i18next.t("battle:countdownPoof"), forgetSuccessText, i18next.t("battle:learnMoveAnd") ].join("$"); this.scene.ui.setMode(this.messageMode).then(() => this.learnMove(moveIndex, move, pokemon, fullText)); }); } @@ -136,20 +149,32 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { * @param Pokemon The Pokemon learning the move */ async learnMove(index: number, move: Move, pokemon: Pokemon, textMessage?: string) { - if (this.fromTM) { + if (this.learnMoveType === LearnMoveType.TM) { if (!pokemon.usedTMs) { pokemon.usedTMs = []; } pokemon.usedTMs.push(this.moveId); + this.scene.tryRemovePhase((phase) => phase instanceof SelectModifierPhase); + } else if (this.learnMoveType === LearnMoveType.MEMORY) { + if (this.cost !== -1) { + if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) { + this.scene.money -= this.cost; + this.scene.updateMoneyText(); + this.scene.animateMoneyChanged(false); + } + this.scene.playSound("se/buy"); + } else { + this.scene.tryRemovePhase((phase) => phase instanceof SelectModifierPhase); + } } pokemon.setMove(index, this.moveId); initMoveAnim(this.scene, this.moveId).then(() => { - loadMoveAnimAssets(this.scene, [this.moveId], true); + loadMoveAnimAssets(this.scene, [ this.moveId ], true); this.scene.playSound("level_up_fanfare"); // Sound loaded into game as is }); this.scene.ui.setMode(this.messageMode); const learnMoveText = i18next.t("battle:learnMove", { pokemonName: getPokemonNameWithAffix(pokemon), moveName: move.name }); - textMessage = textMessage ? textMessage+"$"+learnMoveText : learnMoveText; + textMessage = textMessage ? textMessage + "$" + learnMoveText : learnMoveText; await this.scene.ui.showTextPromise(textMessage, this.messageMode === Mode.EVOLUTION_SCENE ? 1000 : undefined, true); this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true); this.end(); diff --git a/src/phases/level-up-phase.ts b/src/phases/level-up-phase.ts index a99e038acba..a2fa8a16533 100644 --- a/src/phases/level-up-phase.ts +++ b/src/phases/level-up-phase.ts @@ -28,7 +28,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase { this.scene.gameData.gameStats.highestLevel = this.level; } - this.scene.validateAchvs(LevelAchv, new Utils.IntegerHolder(this.level)); + this.scene.validateAchvs(LevelAchv, new Utils.NumberHolder(this.level)); const pokemon = this.getPokemon(); const prevStats = pokemon.stats.slice(0); diff --git a/src/phases/login-phase.ts b/src/phases/login-phase.ts index 89ced201e9e..ac1e68d1b0e 100644 --- a/src/phases/login-phase.ts +++ b/src/phases/login-phase.ts @@ -22,7 +22,7 @@ export class LoginPhase extends Phase { const hasSession = !!Utils.getCookie(Utils.sessionIdKey); - this.scene.ui.setMode(Mode.LOADING, { buttonActions: [] }); + this.scene.ui.setMode(Mode.LOADING, { buttonActions: []}); Utils.executeIf(bypassLogin || hasSession, updateUserInfo).then(response => { const success = response ? response[0] : false; const statusCode = response ? response[1] : null; diff --git a/src/phases/move-anim-test-phase.ts b/src/phases/move-anim-test-phase.ts index a6ab90464b8..e4b04ce5de6 100644 --- a/src/phases/move-anim-test-phase.ts +++ b/src/phases/move-anim-test-phase.ts @@ -29,7 +29,7 @@ export class MoveAnimTestPhase extends BattlePhase { } initMoveAnim(this.scene, moveId).then(() => { - loadMoveAnimAssets(this.scene, [moveId], true) + loadMoveAnimAssets(this.scene, [ moveId ], true) .then(() => { const user = player ? this.scene.getPlayerPokemon()! : this.scene.getEnemyPokemon()!; const target = (player !== (allMoves[moveId] instanceof SelfStatusMove)) ? this.scene.getEnemyPokemon()! : this.scene.getPlayerPokemon()!; diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 33f2394cd1e..dc880f85e23 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -4,7 +4,7 @@ import { applyPreAttackAbAttrs, AddSecondStrikeAbAttr, IgnoreMoveEffectsAbAttr, import { ArenaTagSide, ConditionalProtectTag } from "#app/data/arena-tag"; import { MoveAnim } from "#app/data/battle-anims"; import { BattlerTagLapseType, DamageProtectedTag, ProtectedTag, SemiInvulnerableTag, SubstituteTag } from "#app/data/battler-tags"; -import { MoveTarget, applyMoveAttrs, OverrideMoveEffectAttr, MultiHitAttr, AttackMove, FixedDamageAttr, VariableTargetAttr, MissEffectAttr, MoveFlags, applyFilteredMoveAttrs, MoveAttr, MoveEffectAttr, MoveEffectTrigger, ChargeAttr, MoveCategory, NoEffectAttr, HitsTagAttr, ToxicAccuracyAttr } from "#app/data/move"; +import { MoveTarget, applyMoveAttrs, OverrideMoveEffectAttr, MultiHitAttr, AttackMove, FixedDamageAttr, VariableTargetAttr, MissEffectAttr, MoveFlags, applyFilteredMoveAttrs, MoveAttr, MoveEffectAttr, OneHitKOAttr, MoveEffectTrigger, ChargeAttr, MoveCategory, NoEffectAttr, HitsTagAttr, ToxicAccuracyAttr } from "#app/data/move"; import { SpeciesFormChangePostMoveTrigger } from "#app/data/pokemon-forms"; import { BattlerTagType } from "#app/enums/battler-tag-type"; import { Moves } from "#app/enums/moves"; @@ -70,7 +70,7 @@ export class MoveEffectPhase extends PokemonPhase { * resolve the move's total hit count. This block combines the * effects of the move itself, Parental Bond, and Multi-Lens to do so. */ - if (user.turnData.hitsLeft === undefined) { + if (user.turnData.hitsLeft === -1) { const hitCount = new Utils.IntegerHolder(1); // Assume single target for multi hit applyMoveAttrs(MultiHitAttr, user, this.getTarget() ?? null, move, hitCount); @@ -96,11 +96,12 @@ export class MoveEffectPhase extends PokemonPhase { * Stores results of hit checks of the invoked move against all targets, organized by battler index. * @see {@linkcode hitCheck} */ - const targetHitChecks = Object.fromEntries(targets.map(p => [p.getBattlerIndex(), this.hitCheck(p)])); + const targetHitChecks = Object.fromEntries(targets.map(p => [ p.getBattlerIndex(), this.hitCheck(p) ])); const hasActiveTargets = targets.some(t => t.isActive(true)); - /** Check if the target is immune via ability to the attacking move */ - const isImmune = targets[0].hasAbilityWithAttr(TypeImmunityAbAttr) && (targets[0].getAbility()?.getAttrs(TypeImmunityAbAttr)?.[0]?.getImmuneType() === user.getMoveType(move)); + /** Check if the target is immune via ability to the attacking move, and NOT in semi invulnerable state */ + const isImmune = targets[0].hasAbilityWithAttr(TypeImmunityAbAttr) && (targets[0].getAbility()?.getAttrs(TypeImmunityAbAttr)?.[0]?.getImmuneType() === user.getMoveType(move)) + && !targets[0].getTag(SemiInvulnerableTag); /** * If no targets are left for the move to hit (FAIL), or the invoked move is single-target @@ -111,7 +112,7 @@ export class MoveEffectPhase extends PokemonPhase { if (!hasActiveTargets || (!move.hasAttr(VariableTargetAttr) && !move.isMultiTarget() && !targetHitChecks[this.targets[0]] && !targets[0].getTag(ProtectedTag) && !isImmune)) { this.stopMultiHit(); if (hasActiveTargets) { - this.scene.queueMessage(i18next.t("battle:attackMissed", { pokemonNameWithAffix: this.getTarget()? getPokemonNameWithAffix(this.getTarget()!) : "" })); + this.scene.queueMessage(i18next.t("battle:attackMissed", { pokemonNameWithAffix: this.getTarget() ? getPokemonNameWithAffix(this.getTarget()!) : "" })); moveHistoryEntry.result = MoveResult.MISS; applyMoveAttrs(MissEffectAttr, user, null, move); } else { @@ -140,7 +141,7 @@ export class MoveEffectPhase extends PokemonPhase { const bypassIgnoreProtect = new Utils.BooleanHolder(false); /** If the move is not targeting a Pokemon on the user's side, try to apply conditional protection effects */ if (!this.move.getMove().isAllyTarget()) { - this.scene.arena.applyTagsForSide(ConditionalProtectTag, targetSide, hasConditionalProtectApplied, user, target, move.id, bypassIgnoreProtect); + this.scene.arena.applyTagsForSide(ConditionalProtectTag, targetSide, false, hasConditionalProtectApplied, user, target, move.id, bypassIgnoreProtect); } /** Is the target protected by Protect, etc. or a relevant conditional protection effect? */ @@ -148,8 +149,9 @@ export class MoveEffectPhase extends PokemonPhase { && (hasConditionalProtectApplied.value || (!target.findTags(t => t instanceof DamageProtectedTag).length && target.findTags(t => t instanceof ProtectedTag).find(t => target.lapseTag(t.tagType))) || (this.move.getMove().category !== MoveCategory.STATUS && target.findTags(t => t instanceof DamageProtectedTag).find(t => target.lapseTag(t.tagType)))); - /** Is the pokemon immune due to an ablility? */ - const isImmune = target.hasAbilityWithAttr(TypeImmunityAbAttr) && (target.getAbility()?.getAttrs(TypeImmunityAbAttr)?.[0]?.getImmuneType() === user.getMoveType(move)); + /** Is the pokemon immune due to an ablility, and also not in a semi invulnerable state? */ + const isImmune = target.hasAbilityWithAttr(TypeImmunityAbAttr) && (target.getAbility()?.getAttrs(TypeImmunityAbAttr)?.[0]?.getImmuneType() === user.getMoveType(move)) + && !target.getTag(SemiInvulnerableTag); /** * If the move missed a target, stop all future hits against that target @@ -376,7 +378,7 @@ export class MoveEffectPhase extends PokemonPhase { */ hitCheck(target: Pokemon): boolean { // Moves targeting the user and entry hazards can't miss - if ([MoveTarget.USER, MoveTarget.ENEMY_SIDE].includes(this.move.getMove().moveTarget)) { + if ([ MoveTarget.USER, MoveTarget.ENEMY_SIDE ].includes(this.move.getMove().moveTarget)) { return true; } @@ -404,10 +406,14 @@ export class MoveEffectPhase extends PokemonPhase { return true; } + if (target.getTag(BattlerTagType.TELEKINESIS) && !target.getTag(SemiInvulnerableTag) && !this.move.getMove().hasAttr(OneHitKOAttr)) { + return true; + } + const semiInvulnerableTag = target.getTag(SemiInvulnerableTag); if (semiInvulnerableTag && !this.move.getMove().getAttrs(HitsTagAttr).some(hta => hta.tagType === semiInvulnerableTag.tagType) - && !(this.move.getMove().getAttrs(ToxicAccuracyAttr) && user.isOfType(Type.POISON)) + && !(this.move.getMove().hasAttr(ToxicAccuracyAttr) && user.isOfType(Type.POISON)) ) { return false; } diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index 0a75c32bac3..0af61918636 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -1,5 +1,5 @@ -import BattleScene from "#app/battle-scene"; import { BattlerIndex } from "#app/battle"; +import BattleScene from "#app/battle-scene"; import { applyAbAttrs, applyPostMoveUsedAbAttrs, applyPreAttackAbAttrs, BlockRedirectAbAttr, IncreasePpAbAttr, PokemonTypeChangeAbAttr, PostMoveUsedAbAttr, RedirectMoveAbAttr } from "#app/data/ability"; import { CommonAnim } from "#app/data/battle-anims"; import { BattlerTagLapseType, CenterOfAttentionTag } from "#app/data/battler-tags"; @@ -8,290 +8,443 @@ import { SpeciesFormChangePreMoveTrigger } from "#app/data/pokemon-forms"; import { getStatusEffectActivationText, getStatusEffectHealText } from "#app/data/status-effect"; import { Type } from "#app/data/type"; import { getTerrainBlockMessage } from "#app/data/weather"; -import { Abilities } from "#app/enums/abilities"; -import { BattlerTagType } from "#app/enums/battler-tag-type"; -import { Moves } from "#app/enums/moves"; -import { StatusEffect } from "#app/enums/status-effect"; import { MoveUsedEvent } from "#app/events/battle-scene"; import Pokemon, { MoveResult, PokemonMove, TurnMove } from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; -import * as Utils from "#app/utils"; +import { BattlePhase } from "#app/phases/battle-phase"; +import { CommonAnimPhase } from "#app/phases/common-anim-phase"; +import { MoveEffectPhase } from "#app/phases/move-effect-phase"; +import { MoveEndPhase } from "#app/phases/move-end-phase"; +import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; +import { BooleanHolder, NumberHolder } from "#app/utils"; +import { Abilities } from "#enums/abilities"; +import { BattlerTagType } from "#enums/battler-tag-type"; +import { Moves } from "#enums/moves"; +import { StatusEffect } from "#enums/status-effect"; import i18next from "i18next"; -import { BattlePhase } from "./battle-phase"; -import { CommonAnimPhase } from "./common-anim-phase"; -import { MoveEffectPhase } from "./move-effect-phase"; -import { MoveEndPhase } from "./move-end-phase"; -import { ShowAbilityPhase } from "./show-ability-phase"; export class MovePhase extends BattlePhase { - public pokemon: Pokemon; - public move: PokemonMove; - public targets: BattlerIndex[]; + protected _pokemon: Pokemon; + protected _move: PokemonMove; + protected _targets: BattlerIndex[]; protected followUp: boolean; protected ignorePp: boolean; - protected failed: boolean; - protected cancelled: boolean; + protected failed: boolean = false; + protected cancelled: boolean = false; - constructor(scene: BattleScene, pokemon: Pokemon, targets: BattlerIndex[], move: PokemonMove, followUp?: boolean, ignorePp?: boolean) { + public get pokemon(): Pokemon { + return this._pokemon; + } + + protected set pokemon(pokemon: Pokemon) { + this._pokemon = pokemon; + } + + public get move(): PokemonMove { + return this._move; + } + + protected set move(move: PokemonMove) { + this._move = move; + } + + public get targets(): BattlerIndex[] { + return this._targets; + } + + protected set targets(targets: BattlerIndex[]) { + this._targets = targets; + } + + /** + * @param followUp Indicates that the move being uses is a "follow-up" - for example, a move being used by Metronome or Dancer. + * Follow-ups bypass a few failure conditions, including flinches, sleep/paralysis/freeze and volatile status checks, etc. + */ + constructor(scene: BattleScene, pokemon: Pokemon, targets: BattlerIndex[], move: PokemonMove, followUp: boolean = false, ignorePp: boolean = false) { super(scene); this.pokemon = pokemon; this.targets = targets; this.move = move; - this.followUp = followUp ?? false; - this.ignorePp = ignorePp ?? false; - this.failed = false; - this.cancelled = false; + this.followUp = followUp; + this.ignorePp = ignorePp; } - canMove(ignoreDisableTags?: boolean): boolean { + /** + * Checks if the pokemon is active, if the move is usable, and that the move is targetting something. + * @param ignoreDisableTags `true` to not check if the move is disabled + * @returns `true` if all the checks pass + */ + public canMove(ignoreDisableTags: boolean = false): boolean { return this.pokemon.isActive(true) && this.move.isUsable(this.pokemon, this.ignorePp, ignoreDisableTags) && !!this.targets.length; } /**Signifies the current move should fail but still use PP */ - fail(): void { + public fail(): void { this.failed = true; } /**Signifies the current move should cancel and retain PP */ - cancel(): void { + public cancel(): void { this.cancelled = true; } - start() { + public start(): void { super.start(); console.log(Moves[this.move.moveId]); + // Check if move is unusable (e.g. because it's out of PP due to a mid-turn Spite). if (!this.canMove(true)) { - if (this.pokemon.isActive(true) && this.move.ppUsed >= this.move.getMovePp()) { // if the move PP was reduced from Spite or otherwise, the move fails + if (this.pokemon.isActive(true) && this.move.ppUsed >= this.move.getMovePp()) { this.fail(); this.showMoveText(); this.showFailedText(); } + return this.end(); } + this.pokemon.turnData.acted = true; + + // Reset hit-related turn data when starting follow-up moves (e.g. Metronomed moves, Dancer repeats) + if (this.followUp) { + this.pokemon.turnData.hitsLeft = -1; + this.pokemon.turnData.hitCount = 0; + } + + // Check move to see if arena.ignoreAbilities should be true. if (!this.followUp) { if (this.move.getMove().checkFlag(MoveFlags.IGNORE_ABILITIES, this.pokemon, null)) { this.scene.arena.setIgnoreAbilities(true, this.pokemon.getBattlerIndex()); } + } + + this.resolveRedirectTarget(); + + this.resolveCounterAttackTarget(); + + this.resolvePreMoveStatusEffects(); + + this.lapsePreMoveAndMoveTags(); + + if (!(this.failed || this.cancelled)) { + this.resolveFinalPreMoveCancellationChecks(); + } + + if (this.cancelled || this.failed) { + this.handlePreMoveFailures(); } else { - this.pokemon.turnData.hitsLeft = 0; // TODO: is `0` correct? - this.pokemon.turnData.hitCount = 0; // TODO: is `0` correct? + this.useMove(); } - // Move redirection abilities (ie. Storm Drain) only support single target moves - const moveTarget = this.targets.length === 1 - ? new Utils.IntegerHolder(this.targets[0]) - : null; - if (moveTarget) { - const oldTarget = moveTarget.value; - this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, false, this.move.moveId, moveTarget)); - this.pokemon.getOpponents().forEach(p => { - const redirectTag = p.getTag(CenterOfAttentionTag) as CenterOfAttentionTag; - if (redirectTag && (!redirectTag.powder || (!this.pokemon.isOfType(Type.GRASS) && !this.pokemon.hasAbility(Abilities.OVERCOAT)))) { - moveTarget.value = p.getBattlerIndex(); - } - }); - //Check if this move is immune to being redirected, and restore its target to the intended target if it is. - if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) || this.move.getMove().hasAttr(BypassRedirectAttr))) { - //If an ability prevented this move from being redirected, display its ability pop up. - if ((this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr) && !this.move.getMove().hasAttr(BypassRedirectAttr)) && oldTarget !== moveTarget.value) { - this.scene.unshiftPhase(new ShowAbilityPhase(this.scene, this.pokemon.getBattlerIndex(), this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr))); - } - moveTarget.value = oldTarget; - } - this.targets[0] = moveTarget.value; + this.end(); + } + + /** Check for cancellation edge cases - no targets remaining, or {@linkcode Moves.NONE} is in the queue */ + protected resolveFinalPreMoveCancellationChecks(): void { + const targets = this.getActiveTargetPokemon(); + const moveQueue = this.pokemon.getMoveQueue(); + + if (targets.length === 0 || (moveQueue.length && moveQueue[0].move === Moves.NONE)) { + this.showMoveText(); + this.showFailedText(); + this.cancel(); } + } - // Check for counterattack moves to switch target - if (this.targets.length === 1 && this.targets[0] === BattlerIndex.ATTACKER) { - if (this.pokemon.turnData.attacksReceived.length) { - const attack = this.pokemon.turnData.attacksReceived[0]; - this.targets[0] = attack.sourceBattlerIndex; - - // account for metal burst and comeuppance hitting remaining targets in double battles - // counterattack will redirect to remaining ally if original attacker faints - if (this.scene.currentBattle.double && this.move.getMove().hasFlag(MoveFlags.REDIRECT_COUNTER)) { - if (this.scene.getField()[this.targets[0]].hp === 0) { - const opposingField = this.pokemon.isPlayer() ? this.scene.getEnemyField() : this.scene.getPlayerField(); - //@ts-ignore - this.targets[0] = opposingField.find(p => p.hp > 0)?.getBattlerIndex(); //TODO: fix ts-ignore - } - } - } - if (this.targets[0] === BattlerIndex.ATTACKER) { - this.fail(); // Marks the move as failed for later in doMove - this.showMoveText(); - this.showFailedText(); - } - } - - const targets = this.scene.getField(true).filter(p => { - if (this.targets.indexOf(p.getBattlerIndex()) > -1) { - return true; - } - return false; - }); - - const doMove = () => { - this.pokemon.turnData.acted = true; // Record that the move was attempted, even if it fails - - this.pokemon.lapseTags(BattlerTagLapseType.PRE_MOVE); - - let ppUsed = 1; - // Filter all opponents to include only those this move is targeting - const targetedOpponents = this.pokemon.getOpponents().filter(o => this.targets.includes(o.getBattlerIndex())); - for (const opponent of targetedOpponents) { - if (this.move.ppUsed + ppUsed >= this.move.getMovePp()) { // If we're already at max PP usage, stop checking - break; - } - if (opponent.hasAbilityWithAttr(IncreasePpAbAttr)) { // Accounting for abilities like Pressure - ppUsed++; - } - } - - if (!this.followUp && this.canMove() && !this.cancelled) { - this.pokemon.lapseTags(BattlerTagLapseType.MOVE); - } - - const moveQueue = this.pokemon.getMoveQueue(); - if (this.cancelled || this.failed) { - if (this.failed) { - this.move.usePp(ppUsed); // Only use PP if the move failed - this.scene.eventTarget.dispatchEvent(new MoveUsedEvent(this.pokemon?.id, this.move.getMove(), this.move.ppUsed)); - } - - // Record a failed move so Abilities like Truant don't trigger next turn and soft-lock - this.pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.FAIL }); - - this.pokemon.lapseTags(BattlerTagLapseType.MOVE_EFFECT); // Remove any tags from moves like Fly/Dive/etc. - this.pokemon.lapseTags(BattlerTagLapseType.AFTER_MOVE); - moveQueue.shift(); // Remove the second turn of charge moves - return this.end(); - } - - this.scene.triggerPokemonFormChange(this.pokemon, SpeciesFormChangePreMoveTrigger); - - if (this.move.moveId) { - this.showMoveText(); - } - - // This should only happen when there are no valid targets left on the field - if ((moveQueue.length && moveQueue[0].move === Moves.NONE) || !targets.length) { - this.showFailedText(); - this.cancel(); - - // Record a failed move so Abilities like Truant don't trigger next turn and soft-lock - this.pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.FAIL }); - - this.pokemon.lapseTags(BattlerTagLapseType.MOVE_EFFECT); // Remove any tags from moves like Fly/Dive/etc. - this.pokemon.lapseTags(BattlerTagLapseType.AFTER_MOVE); - - moveQueue.shift(); - return this.end(); - } - - if ((!moveQueue.length || !moveQueue.shift()?.ignorePP) && !this.ignorePp) { // using .shift here clears out two turn moves once they've been used - this.move.usePp(ppUsed); - this.scene.eventTarget.dispatchEvent(new MoveUsedEvent(this.pokemon?.id, this.move.getMove(), this.move.ppUsed)); - } - - if (!allMoves[this.move.moveId].hasAttr(CopyMoveAttr)) { - this.scene.currentBattle.lastMove = this.move.moveId; - } - - // Assume conditions affecting targets only apply to moves with a single target - let success = this.move.getMove().applyConditions(this.pokemon, targets[0], this.move.getMove()); - const cancelled = new Utils.BooleanHolder(false); - let failedText = this.move.getMove().getFailedText(this.pokemon, targets[0], this.move.getMove(), cancelled); - if (success && this.scene.arena.isMoveWeatherCancelled(this.pokemon, this.move.getMove())) { - success = false; - } else if (success && this.scene.arena.isMoveTerrainCancelled(this.pokemon, this.targets, this.move.getMove())) { - success = false; - if (failedText === null) { - failedText = getTerrainBlockMessage(targets[0], this.scene.arena.terrain?.terrainType!); // TODO: is this bang correct? - } - } - - /** - * Trigger pokemon type change before playing the move animation - * Will still change the user's type when using Roar, Whirlwind, Trick-or-Treat, and Forest's Curse, - * regardless of whether the move successfully executes or not. - */ - if (success || [Moves.ROAR, Moves.WHIRLWIND, Moves.TRICK_OR_TREAT, Moves.FORESTS_CURSE].includes(this.move.moveId)) { - applyPreAttackAbAttrs(PokemonTypeChangeAbAttr, this.pokemon, null, this.move.getMove()); - } - - if (success) { - this.scene.unshiftPhase(this.getEffectPhase()); - } else { - this.pokemon.pushMoveHistory({ move: this.move.moveId, targets: this.targets, result: MoveResult.FAIL, virtual: this.move.virtual }); - if (!cancelled.value) { - this.showFailedText(failedText); - } - } - // Checks if Dancer ability is triggered - if (this.move.getMove().hasFlag(MoveFlags.DANCE_MOVE) && !this.followUp) { - // Pokemon with Dancer can be on either side of the battle so we check in both cases - this.scene.getPlayerField().forEach(pokemon => { - applyPostMoveUsedAbAttrs(PostMoveUsedAbAttr, pokemon, this.move, this.pokemon, this.targets); - }); - this.scene.getEnemyField().forEach(pokemon => { - applyPostMoveUsedAbAttrs(PostMoveUsedAbAttr, pokemon, this.move, this.pokemon, this.targets); - }); - } - this.end(); - }; + public getActiveTargetPokemon(): Pokemon[] { + return this.scene.getField(true).filter(p => this.targets.includes(p.getBattlerIndex())); + } + /** + * Handles {@link StatusEffect.SLEEP Sleep}/{@link StatusEffect.PARALYSIS Paralysis}/{@link StatusEffect.FREEZE Freeze} rolls and side effects. + */ + protected resolvePreMoveStatusEffects(): void { if (!this.followUp && this.pokemon.status && !this.pokemon.status.isPostTurn()) { this.pokemon.status.incrementTurn(); let activated = false; let healed = false; switch (this.pokemon.status.effect) { - case StatusEffect.PARALYSIS: - if (!this.pokemon.randSeedInt(4)) { - activated = true; - this.cancelled = true; - } - break; - case StatusEffect.SLEEP: - applyMoveAttrs(BypassSleepAttr, this.pokemon, null, this.move.getMove()); - healed = this.pokemon.status.turnCount === this.pokemon.status.cureTurn; - activated = !healed && !this.pokemon.getTag(BattlerTagType.BYPASS_SLEEP); - this.cancelled = activated; - break; - case StatusEffect.FREEZE: - healed = !!this.move.getMove().findAttr(attr => attr instanceof HealStatusEffectAttr && attr.selfTarget && attr.isOfEffect(StatusEffect.FREEZE)) || !this.pokemon.randSeedInt(5); - activated = !healed; - this.cancelled = activated; - break; + case StatusEffect.PARALYSIS: + if (!this.pokemon.randSeedInt(4)) { + activated = true; + this.cancelled = true; + } + break; + case StatusEffect.SLEEP: + applyMoveAttrs(BypassSleepAttr, this.pokemon, null, this.move.getMove()); + healed = this.pokemon.status.turnCount === this.pokemon.status.cureTurn; + activated = !healed && !this.pokemon.getTag(BattlerTagType.BYPASS_SLEEP); + this.cancelled = activated; + break; + case StatusEffect.FREEZE: + healed = !!this.move.getMove().findAttr(attr => attr instanceof HealStatusEffectAttr && attr.selfTarget && attr.isOfEffect(StatusEffect.FREEZE)) || !this.pokemon.randSeedInt(5); + activated = !healed; + this.cancelled = activated; + break; } if (activated) { this.scene.queueMessage(getStatusEffectActivationText(this.pokemon.status.effect, getPokemonNameWithAffix(this.pokemon))); this.scene.unshiftPhase(new CommonAnimPhase(this.scene, this.pokemon.getBattlerIndex(), undefined, CommonAnim.POISON + (this.pokemon.status.effect - 1))); - doMove(); - } else { - if (healed) { - this.scene.queueMessage(getStatusEffectHealText(this.pokemon.status.effect, getPokemonNameWithAffix(this.pokemon))); - this.pokemon.resetStatus(); - this.pokemon.updateInfo(); - } - doMove(); + } else if (healed) { + this.scene.queueMessage(getStatusEffectHealText(this.pokemon.status.effect, getPokemonNameWithAffix(this.pokemon))); + this.pokemon.resetStatus(); + this.pokemon.updateInfo(); } - } else { - doMove(); } } - getEffectPhase(): MoveEffectPhase { - return new MoveEffectPhase(this.scene, this.pokemon.getBattlerIndex(), this.targets, this.move); + /** + * Lapse {@linkcode BattlerTagLapseType.PRE_MOVE PRE_MOVE} tags that trigger before a move is used, regardless of whether or not it failed. + * Also lapse {@linkcode BattlerTagLapseType.MOVE MOVE} tags if the move should be successful. + */ + protected lapsePreMoveAndMoveTags(): void { + this.pokemon.lapseTags(BattlerTagLapseType.PRE_MOVE); + + // TODO: does this intentionally happen before the no targets/Moves.NONE on queue cancellation case is checked? + if (!this.followUp && this.canMove() && !this.cancelled) { + this.pokemon.lapseTags(BattlerTagLapseType.MOVE); + } } - showMoveText(): void { + protected useMove(): void { + const targets = this.getActiveTargetPokemon(); + const moveQueue = this.pokemon.getMoveQueue(); + + // form changes happen even before we know that the move wll execute. + this.scene.triggerPokemonFormChange(this.pokemon, SpeciesFormChangePreMoveTrigger); + + this.showMoveText(); + + // TODO: Clean up implementation of two-turn moves. + if (moveQueue.length > 0) { + // Using .shift here clears out two turn moves once they've been used + this.ignorePp = moveQueue.shift()?.ignorePP ?? false; + } + + // "commit" to using the move, deducting PP. + if (!this.ignorePp) { + const ppUsed = 1 + this.getPpIncreaseFromPressure(targets); + + this.move.usePp(ppUsed); + this.scene.eventTarget.dispatchEvent(new MoveUsedEvent(this.pokemon?.id, this.move.getMove(), this.move.ppUsed)); + } + + // Update the battle's "last move" pointer, unless we're currently mimicking a move. + if (!allMoves[this.move.moveId].hasAttr(CopyMoveAttr)) { + this.scene.currentBattle.lastMove = this.move.moveId; + } + + /** + * Determine if the move is successful (meaning that its damage/effects can be attempted) + * by checking that all of the following are true: + * - Conditional attributes of the move are all met + * - The target's `ForceSwitchOutImmunityAbAttr` is not triggered (see {@linkcode Move.prototype.applyConditions}) + * - Weather does not block the move + * - Terrain does not block the move + * + * TODO: These steps are straightforward, but the implementation below is extremely convoluted. + */ + + const move = this.move.getMove(); + + /** + * Move conditions assume the move has a single target + * TODO: is this sustainable? + */ + const passesConditions = move.applyConditions(this.pokemon, targets[0], move); + const failedDueToWeather: boolean = this.scene.arena.isMoveWeatherCancelled(this.pokemon, move); + const failedDueToTerrain: boolean = this.scene.arena.isMoveTerrainCancelled(this.pokemon, this.targets, move); + + const success = passesConditions && !failedDueToWeather && !failedDueToTerrain; + + /** + * If the move has not failed, trigger ability-based user type changes and then execute it. + * + * Notably, Roar, Whirlwind, Trick-or-Treat, and Forest's Curse will trigger these type changes even + * if the move fails. + */ + if (success) { + applyPreAttackAbAttrs(PokemonTypeChangeAbAttr, this.pokemon, null, this.move.getMove()); + this.scene.unshiftPhase(new MoveEffectPhase(this.scene, this.pokemon.getBattlerIndex(), this.targets, this.move)); + + } else { + if ([ Moves.ROAR, Moves.WHIRLWIND, Moves.TRICK_OR_TREAT, Moves.FORESTS_CURSE ].includes(this.move.moveId)) { + applyPreAttackAbAttrs(PokemonTypeChangeAbAttr, this.pokemon, null, this.move.getMove()); + } + + this.pokemon.pushMoveHistory({ move: this.move.moveId, targets: this.targets, result: MoveResult.FAIL, virtual: this.move.virtual }); + + let failedText: string | undefined; + const failureMessage = move.getFailedText(this.pokemon, targets[0], move, new BooleanHolder(false)); + + if (failureMessage) { + failedText = failureMessage; + } else if (failedDueToTerrain) { + failedText = getTerrainBlockMessage(this.pokemon, this.scene.arena.getTerrainType()); + } + + this.showFailedText(failedText); + } + + // Handle Dancer, which triggers immediately after a move is used (rather than waiting on `this.end()`). + // Note that the `!this.followUp` check here prevents an infinite Dancer loop. + if (this.move.getMove().hasFlag(MoveFlags.DANCE_MOVE) && !this.followUp) { + this.scene.getField(true).forEach(pokemon => { + applyPostMoveUsedAbAttrs(PostMoveUsedAbAttr, pokemon, this.move, this.pokemon, this.targets); + }); + } + } + + /** + * Queues a {@linkcode MoveEndPhase} if the move wasn't a {@linkcode followUp} and {@linkcode canMove()} returns `true`, + * then ends the phase. + */ + public end(): void { + if (!this.followUp && this.canMove()) { + this.scene.unshiftPhase(new MoveEndPhase(this.scene, this.pokemon.getBattlerIndex())); + } + + super.end(); + } + + /** + * Applies PP increasing abilities (currently only {@link Abilities.PRESSURE Pressure}) if they exist on the target pokemon. + * Note that targets must include only active pokemon. + * + * TODO: This hardcodes the PP increase at 1 per opponent, rather than deferring to the ability. + */ + public getPpIncreaseFromPressure(targets: Pokemon[]): number { + const foesWithPressure = this.pokemon.getOpponents().filter(o => targets.includes(o) && o.isActive(true) && o.hasAbilityWithAttr(IncreasePpAbAttr)); + return foesWithPressure.length; + } + + /** + * Modifies `this.targets` in place, based upon: + * - Move redirection abilities, effects, etc. + * - Counterattacks, which pass a special value into the `targets` constructor param (`[`{@linkcode BattlerIndex.ATTACKER}`]`). + */ + protected resolveRedirectTarget(): void { + if (this.targets.length === 1) { + const currentTarget = this.targets[0]; + const redirectTarget = new NumberHolder(currentTarget); + + // check move redirection abilities of every pokemon *except* the user. + this.scene.getField(true).filter(p => p !== this.pokemon).forEach(p => applyAbAttrs(RedirectMoveAbAttr, p, null, false, this.move.moveId, redirectTarget)); + + /** `true` if an Ability is responsible for redirecting the move to another target; `false` otherwise */ + let redirectedByAbility = (currentTarget !== redirectTarget.value); + + // check for center-of-attention tags (note that this will override redirect abilities) + this.pokemon.getOpponents().forEach(p => { + const redirectTag = p.getTag(CenterOfAttentionTag); + + // TODO: don't hardcode this interaction. + // Handle interaction between the rage powder center-of-attention tag and moves used by grass types/overcoat-havers (which are immune to RP's redirect) + if (redirectTag && (!redirectTag.powder || (!this.pokemon.isOfType(Type.GRASS) && !this.pokemon.hasAbility(Abilities.OVERCOAT)))) { + redirectTarget.value = p.getBattlerIndex(); + redirectedByAbility = false; + } + }); + + if (currentTarget !== redirectTarget.value) { + const bypassRedirectAttrs = this.move.getMove().getAttrs(BypassRedirectAttr); + bypassRedirectAttrs.forEach((attr) => { + if (!attr.abilitiesOnly || redirectedByAbility) { + redirectTarget.value = currentTarget; + } + }); + + if (this.pokemon.hasAbilityWithAttr(BlockRedirectAbAttr)) { + redirectTarget.value = currentTarget; + this.scene.unshiftPhase(new ShowAbilityPhase(this.scene, this.pokemon.getBattlerIndex(), this.pokemon.getPassiveAbility().hasAttr(BlockRedirectAbAttr))); + } + + this.targets[0] = redirectTarget.value; + } + } + } + + /** + * Counter-attacking moves pass in `[`{@linkcode BattlerIndex.ATTACKER}`]` into the constructor's `targets` param. + * This function modifies `this.targets` to reflect the actual battler index of the user's last + * attacker. + * + * If there is no last attacker, or they are no longer on the field, a message is displayed and the + * move is marked for failure. + */ + protected resolveCounterAttackTarget(): void { + if (this.targets.length === 1 && this.targets[0] === BattlerIndex.ATTACKER) { + if (this.pokemon.turnData.attacksReceived.length) { + this.targets[0] = this.pokemon.turnData.attacksReceived[0].sourceBattlerIndex; + + // account for metal burst and comeuppance hitting remaining targets in double battles + // counterattack will redirect to remaining ally if original attacker faints + if (this.scene.currentBattle.double && this.move.getMove().hasFlag(MoveFlags.REDIRECT_COUNTER)) { + if (this.scene.getField()[this.targets[0]].hp === 0) { + const opposingField = this.pokemon.isPlayer() ? this.scene.getEnemyField() : this.scene.getPlayerField(); + this.targets[0] = opposingField.find(p => p.hp > 0)?.getBattlerIndex() ?? BattlerIndex.ATTACKER; + } + } + } + + if (this.targets[0] === BattlerIndex.ATTACKER) { + this.fail(); + this.showMoveText(); + this.showFailedText(); + } + } + } + + /** + * Handles the case where the move was cancelled or failed: + * - Uses PP if the move failed (not cancelled) and should use PP (failed moves are not affected by {@link Abilities.PRESSURE Pressure}) + * - Records a cancelled OR failed move in move history, so abilities like {@link Abilities.TRUANT Truant} don't trigger on the + * next turn and soft-lock. + * - Lapses `MOVE_EFFECT` tags: + * - Semi-invulnerable battler tags (Fly/Dive/etc.) are intended to lapse on move effects, but also need + * to lapse on move failure/cancellation. + * + * TODO: ...this seems weird. + * - Lapses `AFTER_MOVE` tags: + * - This handles the effects of {@link Moves.SUBSTITUTE Substitute} + * - Removes the second turn of charge moves + * + * TODO: handle charge moves more gracefully + */ + protected handlePreMoveFailures(): void { + if (this.cancelled || this.failed) { + if (this.failed) { + const ppUsed = this.ignorePp ? 0 : 1; + + if (ppUsed) { + this.move.usePp(); + } + + this.scene.eventTarget.dispatchEvent(new MoveUsedEvent(this.pokemon?.id, this.move.getMove(), ppUsed)); + } + + this.pokemon.pushMoveHistory({ move: Moves.NONE, result: MoveResult.FAIL }); + + this.pokemon.lapseTags(BattlerTagLapseType.MOVE_EFFECT); + this.pokemon.lapseTags(BattlerTagLapseType.AFTER_MOVE); + + this.pokemon.getMoveQueue().shift(); + } + } + + /** + * Displays the move's usage text to the player, unless it's a charge turn (ie: {@link Moves.SOLAR_BEAM Solar Beam}), + * the pokemon is on a recharge turn (ie: {@link Moves.HYPER_BEAM Hyper Beam}), or a 2-turn move was interrupted (ie: {@link Moves.FLY Fly}). + */ + protected showMoveText(): void { + if (this.move.moveId === Moves.NONE) { + return; + } + if (this.move.getMove().hasAttr(ChargeAttr)) { const lastMove = this.pokemon.getLastXMoves() as TurnMove[]; if (!lastMove.length || lastMove[0].move !== this.move.getMove().id || lastMove[0].result !== MoveResult.OTHER) { @@ -311,18 +464,10 @@ export class MovePhase extends BattlePhase { pokemonNameWithAffix: getPokemonNameWithAffix(this.pokemon), moveName: this.move.getName() }), 500); - applyMoveAttrs(PreMoveMessageAttr, this.pokemon, this.pokemon.getOpponents().find(() => true)!, this.move.getMove()); //TODO: is the bang correct here? + applyMoveAttrs(PreMoveMessageAttr, this.pokemon, this.pokemon.getOpponents()[0], this.move.getMove()); } - showFailedText(failedText: string | null = null): void { - this.scene.queueMessage(failedText || i18next.t("battle:attackFailed")); - } - - end() { - if (!this.followUp && this.canMove()) { - this.scene.unshiftPhase(new MoveEndPhase(this.scene, this.pokemon.getBattlerIndex())); - } - - super.end(); + protected showFailedText(failedText?: string): void { + this.scene.queueMessage(failedText ?? i18next.t("battle:attackFailed")); } } diff --git a/src/phases/mystery-encounter-phases.ts b/src/phases/mystery-encounter-phases.ts index 0efaf1bf4ca..0166b2d6abd 100644 --- a/src/phases/mystery-encounter-phases.ts +++ b/src/phases/mystery-encounter-phases.ts @@ -220,7 +220,7 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase { super.start(); // Lapse any residual flinches/endures but ignore all other turn-end battle tags - const includedLapseTags = [BattlerTagType.FLINCHED, BattlerTagType.ENDURING]; + const includedLapseTags = [ BattlerTagType.FLINCHED, BattlerTagType.ENDURING ]; const field = this.scene.getField(true).filter(p => p.summonData); field.forEach(pokemon => { const tags = pokemon.summonData.tags; diff --git a/src/phases/new-biome-encounter-phase.ts b/src/phases/new-biome-encounter-phase.ts index 2a526a22ee2..eea591c3936 100644 --- a/src/phases/new-biome-encounter-phase.ts +++ b/src/phases/new-biome-encounter-phase.ts @@ -22,7 +22,7 @@ export class NewBiomeEncounterPhase extends NextEncounterPhase { } const enemyField = this.scene.getEnemyField(); - const moveTargets: any[] = [this.scene.arenaEnemy, enemyField]; + const moveTargets: any[] = [ this.scene.arenaEnemy, enemyField ]; const mysteryEncounter = this.scene.currentBattle?.mysteryEncounter?.introVisuals; if (mysteryEncounter) { moveTargets.push(mysteryEncounter); diff --git a/src/phases/next-encounter-phase.ts b/src/phases/next-encounter-phase.ts index d63823e4167..407d7c26b5d 100644 --- a/src/phases/next-encounter-phase.ts +++ b/src/phases/next-encounter-phase.ts @@ -23,7 +23,7 @@ export class NextEncounterPhase extends EncounterPhase { this.scene.arenaNextEnemy.setVisible(true); const enemyField = this.scene.getEnemyField(); - const moveTargets: any[] = [this.scene.arenaEnemy, this.scene.arenaNextEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.lastEnemyTrainer]; + const moveTargets: any[] = [ this.scene.arenaEnemy, this.scene.arenaNextEnemy, this.scene.currentBattle.trainer, enemyField, this.scene.lastEnemyTrainer ]; const lastEncounterVisuals = this.scene.lastMysteryEncounter?.introVisuals; if (lastEncounterVisuals) { moveTargets.push(lastEncounterVisuals); diff --git a/src/phases/obtain-status-effect-phase.ts b/src/phases/obtain-status-effect-phase.ts index bf38c432394..c396fa7ba59 100644 --- a/src/phases/obtain-status-effect-phase.ts +++ b/src/phases/obtain-status-effect-phase.ts @@ -6,7 +6,6 @@ import { StatusEffect } from "#app/enums/status-effect"; import Pokemon from "#app/field/pokemon"; import { getPokemonNameWithAffix } from "#app/messages"; import { PokemonPhase } from "./pokemon-phase"; -import { PostTurnStatusEffectPhase } from "./post-turn-status-effect-phase"; export class ObtainStatusEffectPhase extends PokemonPhase { private statusEffect?: StatusEffect | undefined; @@ -33,9 +32,6 @@ export class ObtainStatusEffectPhase extends PokemonPhase { pokemon.updateInfo(true); new CommonBattleAnim(CommonAnim.POISON + (this.statusEffect! - 1), pokemon).play(this.scene, false, () => { this.scene.queueMessage(getStatusEffectObtainText(this.statusEffect, getPokemonNameWithAffix(pokemon), this.sourceText ?? undefined)); - if (pokemon.status?.isPostTurn()) { - this.scene.pushPhase(new PostTurnStatusEffectPhase(this.scene, this.battlerIndex)); - } this.end(); }); return; diff --git a/src/phases/outdated-phase.ts b/src/phases/outdated-phase.ts deleted file mode 100644 index 4baf16d2f56..00000000000 --- a/src/phases/outdated-phase.ts +++ /dev/null @@ -1,13 +0,0 @@ -import BattleScene from "#app/battle-scene"; -import { Phase } from "#app/phase"; -import { Mode } from "#app/ui/ui"; - -export class OutdatedPhase extends Phase { - constructor(scene: BattleScene) { - super(scene); - } - - start(): void { - this.scene.ui.setMode(Mode.OUTDATED); - } -} diff --git a/src/phases/pokemon-anim-phase.ts b/src/phases/pokemon-anim-phase.ts index 50a62837f9c..26ae11d1026 100644 --- a/src/phases/pokemon-anim-phase.ts +++ b/src/phases/pokemon-anim-phase.ts @@ -5,7 +5,6 @@ import Pokemon from "#app/field/pokemon"; import { BattlePhase } from "#app/phases/battle-phase"; - export class PokemonAnimPhase extends BattlePhase { /** The type of animation to play in this phase */ private key: PokemonAnimType; @@ -26,20 +25,20 @@ export class PokemonAnimPhase extends BattlePhase { super.start(); switch (this.key) { - case PokemonAnimType.SUBSTITUTE_ADD: - this.doSubstituteAddAnim(); - break; - case PokemonAnimType.SUBSTITUTE_PRE_MOVE: - this.doSubstitutePreMoveAnim(); - break; - case PokemonAnimType.SUBSTITUTE_POST_MOVE: - this.doSubstitutePostMoveAnim(); - break; - case PokemonAnimType.SUBSTITUTE_REMOVE: - this.doSubstituteRemoveAnim(); - break; - default: - this.end(); + case PokemonAnimType.SUBSTITUTE_ADD: + this.doSubstituteAddAnim(); + break; + case PokemonAnimType.SUBSTITUTE_PRE_MOVE: + this.doSubstitutePreMoveAnim(); + break; + case PokemonAnimType.SUBSTITUTE_POST_MOVE: + this.doSubstitutePostMoveAnim(); + break; + case PokemonAnimType.SUBSTITUTE_REMOVE: + this.doSubstituteRemoveAnim(); + break; + default: + this.end(); } } @@ -53,7 +52,7 @@ export class PokemonAnimPhase extends BattlePhase { const sprite = this.scene.addFieldSprite( this.pokemon.x + this.pokemon.getSprite().x, this.pokemon.y + this.pokemon.getSprite().y, - `pkmn${this.pokemon.isPlayer() ? "__back": ""}__sub` + `pkmn${this.pokemon.isPlayer() ? "__back" : ""}__sub` ); sprite.setOrigin(0.5, 1); this.scene.field.add(sprite); @@ -179,7 +178,7 @@ export class PokemonAnimPhase extends BattlePhase { const sprite = this.scene.addFieldSprite( subSprite.x, subSprite.y, - `pkmn${this.pokemon.isPlayer() ? "__back": ""}__sub` + `pkmn${this.pokemon.isPlayer() ? "__back" : ""}__sub` ); sprite.setOrigin(0.5, 1); this.scene.field.add(sprite); diff --git a/src/phases/post-summon-phase.ts b/src/phases/post-summon-phase.ts index b99c0b90fd8..617bb8b1cfe 100644 --- a/src/phases/post-summon-phase.ts +++ b/src/phases/post-summon-phase.ts @@ -20,7 +20,7 @@ export class PostSummonPhase extends PokemonPhase { if (pokemon.status?.effect === StatusEffect.TOXIC) { pokemon.status.turnCount = 0; } - this.scene.arena.applyTags(ArenaTrapTag, pokemon); + this.scene.arena.applyTags(ArenaTrapTag, false, pokemon); // If this is mystery encounter and has post summon phase tag, apply post summon effects if (this.scene.currentBattle.isBattleMysteryEncounter() && pokemon.findTags(t => t instanceof MysteryEncounterPostSummonTag).length > 0) { diff --git a/src/phases/post-turn-status-effect-phase.ts b/src/phases/post-turn-status-effect-phase.ts index 285bbddde88..06681b733f0 100644 --- a/src/phases/post-turn-status-effect-phase.ts +++ b/src/phases/post-turn-status-effect-phase.ts @@ -26,16 +26,16 @@ export class PostTurnStatusEffectPhase extends PokemonPhase { this.scene.queueMessage(getStatusEffectActivationText(pokemon.status.effect, getPokemonNameWithAffix(pokemon))); const damage = new Utils.NumberHolder(0); switch (pokemon.status.effect) { - case StatusEffect.POISON: - damage.value = Math.max(pokemon.getMaxHp() >> 3, 1); - break; - case StatusEffect.TOXIC: - damage.value = Math.max(Math.floor((pokemon.getMaxHp() / 16) * pokemon.status.turnCount), 1); - break; - case StatusEffect.BURN: - damage.value = Math.max(pokemon.getMaxHp() >> 4, 1); - applyAbAttrs(ReduceBurnDamageAbAttr, pokemon, null, false, damage); - break; + case StatusEffect.POISON: + damage.value = Math.max(pokemon.getMaxHp() >> 3, 1); + break; + case StatusEffect.TOXIC: + damage.value = Math.max(Math.floor((pokemon.getMaxHp() / 16) * pokemon.status.turnCount), 1); + break; + case StatusEffect.BURN: + damage.value = Math.max(pokemon.getMaxHp() >> 4, 1); + applyAbAttrs(ReduceBurnDamageAbAttr, pokemon, null, false, damage); + break; } if (damage.value) { // Set preventEndure flag to avoid pokemon surviving thanks to focus band, sturdy, endure ... diff --git a/src/phases/select-biome-phase.ts b/src/phases/select-biome-phase.ts index 49c6c3ac3c0..817cd7bcd3d 100644 --- a/src/phases/select-biome-phase.ts +++ b/src/phases/select-biome-phase.ts @@ -45,7 +45,7 @@ export class SelectBiomePhase extends BattlePhase { let biomeChoices: Biome[] = []; this.scene.executeWithSeedOffset(() => { biomeChoices = (!Array.isArray(biomeLinks[currentBiome]) - ? [biomeLinks[currentBiome] as Biome] + ? [ biomeLinks[currentBiome] as Biome ] : biomeLinks[currentBiome] as (Biome | [Biome, integer])[]) .filter((b, i) => !Array.isArray(b) || !Utils.randSeedInt(b[1])) .map(b => Array.isArray(b) ? b[0] : b); diff --git a/src/phases/select-modifier-phase.ts b/src/phases/select-modifier-phase.ts index 38727368e7c..f7bac4373b9 100644 --- a/src/phases/select-modifier-phase.ts +++ b/src/phases/select-modifier-phase.ts @@ -16,26 +16,32 @@ export class SelectModifierPhase extends BattlePhase { private rerollCount: integer; private modifierTiers?: ModifierTier[]; private customModifierSettings?: CustomModifierSettings; + private isCopy: boolean; - constructor(scene: BattleScene, rerollCount: integer = 0, modifierTiers?: ModifierTier[], customModifierSettings?: CustomModifierSettings) { + private typeOptions: ModifierTypeOption[]; + + constructor(scene: BattleScene, rerollCount: integer = 0, modifierTiers?: ModifierTier[], customModifierSettings?: CustomModifierSettings, isCopy: boolean = false) { super(scene); this.rerollCount = rerollCount; this.modifierTiers = modifierTiers; this.customModifierSettings = customModifierSettings; + this.isCopy = isCopy; } start() { super.start(); - if (!this.rerollCount) { + if (!this.rerollCount && !this.isCopy) { this.updateSeed(); - } else { + } else if (this.rerollCount) { this.scene.reroll = false; } const party = this.scene.getParty(); - regenerateModifierPoolThresholds(party, this.getPoolType(), this.rerollCount); + if (!this.isCopy) { + regenerateModifierPoolThresholds(party, this.getPoolType(), this.rerollCount); + } const modifierCount = new Utils.IntegerHolder(3); if (this.isPlayer()) { this.scene.applyModifiers(ExtraModifierModifier, true, modifierCount); @@ -55,7 +61,7 @@ export class SelectModifierPhase extends BattlePhase { } } - const typeOptions: ModifierTypeOption[] = this.getModifierTypeOptions(modifierCount.value); + this.typeOptions = this.getModifierTypeOptions(modifierCount.value); const modifierSelectCallback = (rowCursor: integer, cursor: integer) => { if (rowCursor < 0 || cursor < 0) { @@ -64,86 +70,86 @@ export class SelectModifierPhase extends BattlePhase { this.scene.ui.revertMode(); this.scene.ui.setMode(Mode.MESSAGE); super.end(); - }, () => this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers))); + }, () => this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers))); }); return false; } let modifierType: ModifierType; let cost: integer; - const rerollCost = this.getRerollCost(typeOptions, this.scene.lockModifierTiers); + const rerollCost = this.getRerollCost(this.scene.lockModifierTiers); switch (rowCursor) { - case 0: - switch (cursor) { case 0: - if (rerollCost < 0 || this.scene.money < rerollCost) { - this.scene.ui.playError(); - return false; - } else { - this.scene.reroll = true; - this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1, typeOptions.map(o => o.type?.tier).filter(t => t !== undefined) as ModifierTier[])); - this.scene.ui.clearText(); - this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end()); - if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) { - this.scene.money -= rerollCost; - this.scene.updateMoneyText(); - this.scene.animateMoneyChanged(false); - } - this.scene.playSound("se/buy"); - } - break; - case 1: - this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => { - if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) { - const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier + switch (cursor) { + case 0: + if (rerollCost < 0 || this.scene.money < rerollCost) { + this.scene.ui.playError(); + return false; + } else { + this.scene.reroll = true; + this.scene.unshiftPhase(new SelectModifierPhase(this.scene, this.rerollCount + 1, this.typeOptions.map(o => o.type?.tier).filter(t => t !== undefined) as ModifierTier[])); + this.scene.ui.clearText(); + this.scene.ui.setMode(Mode.MESSAGE).then(() => super.end()); + if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) { + this.scene.money -= rerollCost; + this.scene.updateMoneyText(); + this.scene.animateMoneyChanged(false); + } + this.scene.playSound("se/buy"); + } + break; + case 1: + this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.MODIFIER_TRANSFER, -1, (fromSlotIndex: integer, itemIndex: integer, itemQuantity: integer, toSlotIndex: integer) => { + if (toSlotIndex !== undefined && fromSlotIndex < 6 && toSlotIndex < 6 && fromSlotIndex !== toSlotIndex && itemIndex > -1) { + const itemModifiers = this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier && m.isTransferable && m.pokemonId === party[fromSlotIndex].id) as PokemonHeldItemModifier[]; - const itemModifier = itemModifiers[itemIndex]; - this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity); - } else { - this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); - } - }, PartyUiHandler.FilterItemMaxStacks); - break; - case 2: - this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.CHECK, -1, () => { - this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); - }); - break; - case 3: - if (rerollCost < 0) { - // Reroll lock button is also disabled when reroll is disabled - this.scene.ui.playError(); - return false; + const itemModifier = itemModifiers[itemIndex]; + this.scene.tryTransferHeldItemModifier(itemModifier, party[toSlotIndex], true, itemQuantity); + } else { + this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers)); + } + }, PartyUiHandler.FilterItemMaxStacks); + break; + case 2: + this.scene.ui.setModeWithoutClear(Mode.PARTY, PartyUiMode.CHECK, -1, () => { + this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers)); + }); + break; + case 3: + if (rerollCost < 0) { + // Reroll lock button is also disabled when reroll is disabled + this.scene.ui.playError(); + return false; + } + this.scene.lockModifierTiers = !this.scene.lockModifierTiers; + const uiHandler = this.scene.ui.getHandler() as ModifierSelectUiHandler; + uiHandler.setRerollCost(this.getRerollCost(this.scene.lockModifierTiers)); + uiHandler.updateLockRaritiesText(); + uiHandler.updateRerollCostText(); + return false; } - this.scene.lockModifierTiers = !this.scene.lockModifierTiers; - const uiHandler = this.scene.ui.getHandler() as ModifierSelectUiHandler; - uiHandler.setRerollCost(this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); - uiHandler.updateLockRaritiesText(); - uiHandler.updateRerollCostText(); - return false; - } - return true; - case 1: - if (typeOptions.length === 0) { - this.scene.ui.clearText(); - this.scene.ui.setMode(Mode.MESSAGE); - super.end(); return true; - } - if (typeOptions[cursor].type) { - modifierType = typeOptions[cursor].type; - } - break; - default: - const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1)); - const shopOption = shopOptions[rowCursor > 2 || shopOptions.length <= SHOP_OPTIONS_ROW_LIMIT ? cursor : cursor + SHOP_OPTIONS_ROW_LIMIT]; - if (shopOption.type) { - modifierType = shopOption.type; - } - // Apply Black Sludge to healing item cost - const healingItemCost = new NumberHolder(shopOption.cost); - this.scene.applyModifier(HealShopCostModifier, true, healingItemCost); - cost = healingItemCost.value; - break; + case 1: + if (this.typeOptions.length === 0) { + this.scene.ui.clearText(); + this.scene.ui.setMode(Mode.MESSAGE); + super.end(); + return true; + } + if (this.typeOptions[cursor].type) { + modifierType = this.typeOptions[cursor].type; + } + break; + default: + const shopOptions = getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, this.scene.getWaveMoneyAmount(1)); + const shopOption = shopOptions[rowCursor > 2 || shopOptions.length <= SHOP_OPTIONS_ROW_LIMIT ? cursor : cursor + SHOP_OPTIONS_ROW_LIMIT]; + if (shopOption.type) { + modifierType = shopOption.type; + } + // Apply Black Sludge to healing item cost + const healingItemCost = new NumberHolder(shopOption.cost); + this.scene.applyModifier(HealShopCostModifier, true, healingItemCost); + cost = healingItemCost.value; + break; } if (cost! && (this.scene.money < cost) && !Overrides.WAIVE_ROLL_FEE_OVERRIDE) { // TODO: is the bang on cost correct? @@ -152,8 +158,16 @@ export class SelectModifierPhase extends BattlePhase { } const applyModifier = (modifier: Modifier, playSound: boolean = false) => { - const result = this.scene.addModifier(modifier, false, playSound); - if (cost) { + const result = this.scene.addModifier(modifier, false, playSound, undefined, undefined, cost); + // Queue a copy of this phase when applying a TM or Memory Mushroom. + // If the player selects either of these, then escapes out of consuming them, + // they are returned to a shop in the same state. + if (modifier.type instanceof RememberMoveModifierType || + modifier.type instanceof TmModifierType) { + this.scene.unshiftPhase(this.copy()); + } + + if (cost && !(modifier.type instanceof RememberMoveModifierType)) { result.then(success => { if (success) { if (!Overrides.WAIVE_ROLL_FEE_OVERRIDE) { @@ -190,7 +204,7 @@ export class SelectModifierPhase extends BattlePhase { applyModifier(modifier, true); }); } else { - this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); + this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers)); } }, modifierType.selectFilter); } else { @@ -217,7 +231,7 @@ export class SelectModifierPhase extends BattlePhase { applyModifier(modifier!, true); // TODO: is the bang correct? }); } else { - this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); + this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers)); } }, pokemonModifierType.selectFilter, modifierType instanceof PokemonMoveModifierType ? (modifierType as PokemonMoveModifierType).moveSelectFilter : undefined, tmMoveId, isPpRestoreModifier); } @@ -227,7 +241,7 @@ export class SelectModifierPhase extends BattlePhase { return !cost!;// TODO: is the bang correct? }; - this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), typeOptions, modifierSelectCallback, this.getRerollCost(typeOptions, this.scene.lockModifierTiers)); + this.scene.ui.setMode(Mode.MODIFIER_SELECT, this.isPlayer(), this.typeOptions, modifierSelectCallback, this.getRerollCost(this.scene.lockModifierTiers)); } updateSeed(): void { @@ -238,13 +252,13 @@ export class SelectModifierPhase extends BattlePhase { return true; } - getRerollCost(typeOptions: ModifierTypeOption[], lockRarities: boolean): number { + getRerollCost(lockRarities: boolean): number { let baseValue = 0; if (Overrides.WAIVE_ROLL_FEE_OVERRIDE) { return baseValue; } else if (lockRarities) { - const tierValues = [50, 125, 300, 750, 2000]; - for (const opt of typeOptions) { + const tierValues = [ 50, 125, 300, 750, 2000 ]; + for (const opt of this.typeOptions) { baseValue += tierValues[opt.type.tier ?? 0]; } } else { @@ -278,6 +292,16 @@ export class SelectModifierPhase extends BattlePhase { return getPlayerModifierTypeOptions(modifierCount, this.scene.getParty(), this.scene.lockModifierTiers ? this.modifierTiers : undefined, this.customModifierSettings); } + copy(): SelectModifierPhase { + return new SelectModifierPhase( + this.scene, + this.rerollCount, + this.modifierTiers, + { guaranteedModifierTypeOptions: this.typeOptions, rerollMultiplier: this.customModifierSettings?.rerollMultiplier, allowLuckUpgrades: false }, + true + ); + } + addModifier(modifier: Modifier): Promise { return this.scene.addModifier(modifier, false, true); } diff --git a/src/phases/select-starter-phase.ts b/src/phases/select-starter-phase.ts index cd3c112549c..1692b5f2234 100644 --- a/src/phases/select-starter-phase.ts +++ b/src/phases/select-starter-phase.ts @@ -80,7 +80,7 @@ export class SelectStarterPhase extends Phase { starterPokemon.nickname = starter.nickname; } - if (this.scene.gameMode.isSplicedOnly) { + if (this.scene.gameMode.isSplicedOnly || Overrides.STARTER_FUSION_OVERRIDE) { starterPokemon.generateFusionSpecies(true); } starterPokemon.setVisible(false); diff --git a/src/phases/stat-stage-change-phase.ts b/src/phases/stat-stage-change-phase.ts index 4418c38c849..4c13b883445 100644 --- a/src/phases/stat-stage-change-phase.ts +++ b/src/phases/stat-stage-change-phase.ts @@ -36,6 +36,16 @@ export class StatStageChangePhase extends PokemonPhase { } start() { + + // Check if multiple stats are being changed at the same time, then run SSCPhase for each of them + if (this.stats.length > 1) { + for (let i = 0; i < this.stats.length; i++) { + const stat = [ this.stats[i] ]; + this.scene.unshiftPhase(new StatStageChangePhase(this.scene, this.battlerIndex, this.selfTarget, stat, this.stages, this.showMessage, this.ignoreAbilities, this.canBeCopied, this.onChange)); + } + return this.end(); + } + const pokemon = this.getPokemon(); if (!pokemon.isActive(true)) { @@ -54,8 +64,7 @@ export class StatStageChangePhase extends PokemonPhase { const cancelled = new BooleanHolder(false); if (!this.selfTarget && stages.value < 0) { - // TODO: Include simulate boolean when tag applications can be simulated - this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, cancelled); + this.scene.arena.applyTagsForSide(MistTag, pokemon.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY, false, cancelled); } if (!cancelled.value && !this.selfTarget && stages.value < 0) { diff --git a/src/phases/summon-phase.ts b/src/phases/summon-phase.ts index dfa374307d5..119e550293c 100644 --- a/src/phases/summon-phase.ts +++ b/src/phases/summon-phase.ts @@ -57,7 +57,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { } // Swaps the fainted Pokemon and the first non-fainted legal Pokemon in the party - [party[this.partyMemberIndex], party[legalIndex]] = [party[legalIndex], party[this.partyMemberIndex]]; + [ party[this.partyMemberIndex], party[legalIndex] ] = [ party[legalIndex], party[this.partyMemberIndex] ]; console.warn("Swapped %s %O with %s %O", getPokemonNameWithAffix(partyMember), partyMember, getPokemonNameWithAffix(party[0]), party[0]); } @@ -240,7 +240,7 @@ export class SummonPhase extends PartyMemberPokemonPhase { pokemon.resetTurnData(); - if (!this.loaded || [BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(this.scene.currentBattle.battleType) || (this.scene.currentBattle.waveIndex % 10) === 1) { + if (!this.loaded || [ BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER ].includes(this.scene.currentBattle.battleType) || (this.scene.currentBattle.waveIndex % 10) === 1) { this.scene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true); this.queuePostSummon(); } diff --git a/src/phases/switch-biome-phase.ts b/src/phases/switch-biome-phase.ts index 9cf5635a39f..80a31794209 100644 --- a/src/phases/switch-biome-phase.ts +++ b/src/phases/switch-biome-phase.ts @@ -20,7 +20,7 @@ export class SwitchBiomePhase extends BattlePhase { } this.scene.tweens.add({ - targets: [this.scene.arenaEnemy, this.scene.lastEnemyTrainer], + targets: [ this.scene.arenaEnemy, this.scene.lastEnemyTrainer ], x: "+=300", duration: 2000, onComplete: () => { @@ -38,7 +38,7 @@ export class SwitchBiomePhase extends BattlePhase { this.scene.arenaPlayerTransition.setVisible(true); this.scene.tweens.add({ - targets: [this.scene.arenaPlayer, this.scene.arenaBgTransition, this.scene.arenaPlayerTransition], + targets: [ this.scene.arenaPlayer, this.scene.arenaBgTransition, this.scene.arenaPlayerTransition ], duration: 1000, delay: 1000, ease: "Sine.easeInOut", diff --git a/src/phases/title-phase.ts b/src/phases/title-phase.ts index b23a5ec0c89..58683cf8ec8 100644 --- a/src/phases/title-phase.ts +++ b/src/phases/title-phase.ts @@ -60,7 +60,7 @@ export class TitlePhase extends Phase { const options: OptionSelectItem[] = []; if (loggedInUser && loggedInUser.lastSessionSlot > -1) { options.push({ - label: i18next.t("continue", {ns: "menu"}), + label: i18next.t("continue", { ns: "menu" }), handler: () => { this.loadSaveSlot(this.lastSessionData || !loggedInUser ? -1 : loggedInUser.lastSessionSlot); return true; @@ -196,7 +196,7 @@ export class TitlePhase extends Phase { this.scene.gameMode = getGameMode(GameModes.DAILY); this.scene.setSeed(seed); - this.scene.resetSeed(1); + this.scene.resetSeed(0); this.scene.money = this.scene.gameMode.getStartingMoney(); @@ -221,7 +221,7 @@ export class TitlePhase extends Phase { const modifiers: Modifier[] = Array(3).fill(null).map(() => modifierTypes.EXP_SHARE().withIdFromFunc(modifierTypes.EXP_SHARE).newModifier()) .concat(Array(3).fill(null).map(() => modifierTypes.GOLDEN_EXP_CHARM().withIdFromFunc(modifierTypes.GOLDEN_EXP_CHARM).newModifier())) - .concat([modifierTypes.MAP().withIdFromFunc(modifierTypes.MAP).newModifier()]) + .concat([ modifierTypes.MAP().withIdFromFunc(modifierTypes.MAP).newModifier() ]) .concat(getDailyRunStarterModifiers(party)) .filter((m) => m !== null); diff --git a/src/phases/trainer-message-test-phase.ts b/src/phases/trainer-message-test-phase.ts index 8075dd761e2..d9e58473bd5 100644 --- a/src/phases/trainer-message-test-phase.ts +++ b/src/phases/trainer-message-test-phase.ts @@ -24,7 +24,7 @@ export class TrainerMessageTestPhase extends BattlePhase { continue; } const config = trainerConfigs[type]; - [config.encounterMessages, config.femaleEncounterMessages, config.victoryMessages, config.femaleVictoryMessages, config.defeatMessages, config.femaleDefeatMessages] + [ config.encounterMessages, config.femaleEncounterMessages, config.victoryMessages, config.femaleVictoryMessages, config.defeatMessages, config.femaleDefeatMessages ] .map(messages => { if (messages?.length) { testMessages.push(...messages); diff --git a/src/phases/trainer-victory-phase.ts b/src/phases/trainer-victory-phase.ts index e925f0c47d4..fd48b91b1a1 100644 --- a/src/phases/trainer-victory-phase.ts +++ b/src/phases/trainer-victory-phase.ts @@ -30,7 +30,7 @@ export class TrainerVictoryPhase extends BattlePhase { const trainerType = this.scene.currentBattle.trainer?.config.trainerType!; // TODO: is this bang correct? if (vouchers.hasOwnProperty(TrainerType[trainerType])) { if (!this.scene.validateVoucher(vouchers[TrainerType[trainerType]]) && this.scene.currentBattle.trainer?.config.isBoss) { - this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM][vouchers[TrainerType[trainerType]].voucherType])); + this.scene.unshiftPhase(new ModifierRewardPhase(this.scene, [ modifierTypes.VOUCHER, modifierTypes.VOUCHER, modifierTypes.VOUCHER_PLUS, modifierTypes.VOUCHER_PREMIUM ][vouchers[TrainerType[trainerType]].voucherType])); } } diff --git a/src/phases/turn-start-phase.ts b/src/phases/turn-start-phase.ts index 95d55986185..497d449912f 100644 --- a/src/phases/turn-start-phase.ts +++ b/src/phases/turn-start-phase.ts @@ -13,10 +13,10 @@ import { BerryPhase } from "./berry-phase"; import { FieldPhase } from "./field-phase"; import { MoveHeaderPhase } from "./move-header-phase"; import { MovePhase } from "./move-phase"; -import { PostTurnStatusEffectPhase } from "./post-turn-status-effect-phase"; import { SwitchSummonPhase } from "./switch-summon-phase"; import { TurnEndPhase } from "./turn-end-phase"; import { WeatherEffectPhase } from "./weather-effect-phase"; +import { CheckStatusEffectPhase } from "#app/phases/check-status-effect-phase"; import { BattlerIndex } from "#app/battle"; import { TrickRoomTag } from "#app/data/arena-tag"; import { SwitchType } from "#enums/switch-type"; @@ -45,7 +45,7 @@ export class TurnStartPhase extends FieldPhase { // Next, a check for Trick Room is applied to determine sort order. const speedReversed = new Utils.BooleanHolder(false); - this.scene.arena.applyTags(TrickRoomTag, speedReversed); + this.scene.arena.applyTags(TrickRoomTag, false, speedReversed); // Adjust the sort function based on whether Trick Room is active. orderedTargets.sort((a: Pokemon, b: Pokemon) => { @@ -152,65 +152,62 @@ export class TurnStartPhase extends FieldPhase { } switch (turnCommand?.command) { - case Command.FIGHT: - const queuedMove = turnCommand.move; - pokemon.turnData.order = orderIndex++; - if (!queuedMove) { - continue; - } - const move = pokemon.getMoveset().find(m => m?.moveId === queuedMove.move) || new PokemonMove(queuedMove.move); - if (move.getMove().hasAttr(MoveHeaderAttr)) { - this.scene.unshiftPhase(new MoveHeaderPhase(this.scene, pokemon, move)); - } - if (pokemon.isPlayer()) { - if (turnCommand.cursor === -1) { - this.scene.pushPhase(new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move));//TODO: is the bang correct here? - } else { - const playerPhase = new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move, false, queuedMove.ignorePP);//TODO: is the bang correct here? - this.scene.pushPhase(playerPhase); + case Command.FIGHT: + const queuedMove = turnCommand.move; + pokemon.turnData.order = orderIndex++; + if (!queuedMove) { + continue; } - } else { - this.scene.pushPhase(new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move, false, queuedMove.ignorePP));//TODO: is the bang correct here? - } - break; - case Command.BALL: - this.scene.unshiftPhase(new AttemptCapturePhase(this.scene, turnCommand.targets![0] % 2, turnCommand.cursor!));//TODO: is the bang correct here? - break; - case Command.POKEMON: - const switchType = turnCommand.args?.[0] ? SwitchType.BATON_PASS : SwitchType.SWITCH; - this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, switchType, pokemon.getFieldIndex(), turnCommand.cursor!, true, pokemon.isPlayer())); - break; - case Command.RUN: - let runningPokemon = pokemon; - if (this.scene.currentBattle.double) { - const playerActivePokemon = field.filter(pokemon => { - if (!!pokemon) { - return pokemon.isPlayer() && pokemon.isActive(); + const move = pokemon.getMoveset().find(m => m?.moveId === queuedMove.move && m?.ppUsed < m?.getMovePp()) || new PokemonMove(queuedMove.move); + if (move.getMove().hasAttr(MoveHeaderAttr)) { + this.scene.unshiftPhase(new MoveHeaderPhase(this.scene, pokemon, move)); + } + if (pokemon.isPlayer()) { + if (turnCommand.cursor === -1) { + this.scene.pushPhase(new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move));//TODO: is the bang correct here? } else { - return; + const playerPhase = new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move, false, queuedMove.ignorePP);//TODO: is the bang correct here? + this.scene.pushPhase(playerPhase); } - }); - // if only one pokemon is alive, use that one - if (playerActivePokemon.length > 1) { - // find which active pokemon has faster speed - const fasterPokemon = playerActivePokemon[0].getStat(Stat.SPD) > playerActivePokemon[1].getStat(Stat.SPD) ? playerActivePokemon[0] : playerActivePokemon[1]; - // check if either active pokemon has the ability "Run Away" - const hasRunAway = playerActivePokemon.find(p => p.hasAbility(Abilities.RUN_AWAY)); - runningPokemon = hasRunAway !== undefined ? hasRunAway : fasterPokemon; + } else { + this.scene.pushPhase(new MovePhase(this.scene, pokemon, turnCommand.targets || turnCommand.move!.targets, move, false, queuedMove.ignorePP));//TODO: is the bang correct here? } - } - this.scene.unshiftPhase(new AttemptRunPhase(this.scene, runningPokemon.getFieldIndex())); - break; + break; + case Command.BALL: + this.scene.unshiftPhase(new AttemptCapturePhase(this.scene, turnCommand.targets![0] % 2, turnCommand.cursor!));//TODO: is the bang correct here? + break; + case Command.POKEMON: + const switchType = turnCommand.args?.[0] ? SwitchType.BATON_PASS : SwitchType.SWITCH; + this.scene.unshiftPhase(new SwitchSummonPhase(this.scene, switchType, pokemon.getFieldIndex(), turnCommand.cursor!, true, pokemon.isPlayer())); + break; + case Command.RUN: + let runningPokemon = pokemon; + if (this.scene.currentBattle.double) { + const playerActivePokemon = field.filter(pokemon => { + if (!!pokemon) { + return pokemon.isPlayer() && pokemon.isActive(); + } else { + return; + } + }); + // if only one pokemon is alive, use that one + if (playerActivePokemon.length > 1) { + // find which active pokemon has faster speed + const fasterPokemon = playerActivePokemon[0].getStat(Stat.SPD) > playerActivePokemon[1].getStat(Stat.SPD) ? playerActivePokemon[0] : playerActivePokemon[1]; + // check if either active pokemon has the ability "Run Away" + const hasRunAway = playerActivePokemon.find(p => p.hasAbility(Abilities.RUN_AWAY)); + runningPokemon = hasRunAway !== undefined ? hasRunAway : fasterPokemon; + } + } + this.scene.unshiftPhase(new AttemptRunPhase(this.scene, runningPokemon.getFieldIndex())); + break; } } this.scene.pushPhase(new WeatherEffectPhase(this.scene)); - for (const o of moveOrder) { - if (field[o].status && field[o].status.isPostTurn()) { - this.scene.pushPhase(new PostTurnStatusEffectPhase(this.scene, o)); - } - } + /** Add a new phase to check who should be taking status damage */ + this.scene.pushPhase(new CheckStatusEffectPhase(this.scene, moveOrder)); this.scene.pushPhase(new BerryPhase(this.scene)); this.scene.pushPhase(new TurnEndPhase(this.scene)); diff --git a/src/plugins/cache-busted-loader-plugin.ts b/src/plugins/cache-busted-loader-plugin.ts index 3ed939c49dd..344da3eaa66 100644 --- a/src/plugins/cache-busted-loader-plugin.ts +++ b/src/plugins/cache-busted-loader-plugin.ts @@ -20,7 +20,7 @@ export default class CacheBustedLoaderPlugin extends Phaser.Loader.LoaderPlugin file.forEach(item => { if (manifest) { - const timestamp = manifest[`/${item.url.replace(/\/\//g, "/")}` ]; + const timestamp = manifest[`/${item.url.replace(/\/\//g, "/")}`]; if (timestamp) { item.url += `?t=${timestamp}`; } diff --git a/src/plugins/i18n.ts b/src/plugins/i18n.ts index 5f7be4768a3..d24484bbf9d 100644 --- a/src/plugins/i18n.ts +++ b/src/plugins/i18n.ts @@ -27,9 +27,9 @@ const unicodeRanges = { }; const rangesByLanguage = { - korean: [unicodeRanges.CJKCommon, unicodeRanges.hangul].join(","), - chinese: [unicodeRanges.CJKCommon, unicodeRanges.fullwidth, unicodeRanges.CJKIdeograph].join(","), - japanese: [unicodeRanges.CJKCommon, unicodeRanges.fullwidth, unicodeRanges.kana, unicodeRanges.CJKIdeograph].join(",") + korean: [ unicodeRanges.CJKCommon, unicodeRanges.hangul ].join(","), + chinese: [ unicodeRanges.CJKCommon, unicodeRanges.fullwidth, unicodeRanges.CJKIdeograph ].join(","), + japanese: [ unicodeRanges.CJKCommon, unicodeRanges.fullwidth, unicodeRanges.kana, unicodeRanges.CJKIdeograph ].join(",") }; const fonts: Array = [ @@ -81,6 +81,8 @@ const namespaceMap = { miscDialogue: "dialogue-misc", battleSpecDialogue: "dialogue-final-boss", doubleBattleDialogue: "dialogue-double-battle", + splashMessages: "splash-texts", + mysteryEncounterMessages: "mystery-encounter-texts", }; //#region Functions @@ -100,6 +102,22 @@ async function initFonts(language: string | undefined) { } } +/** + * I18n money formatter with. (useful for BBCode coloring of text)\ + * *If you don't want the BBCode tag applied, just use 'number' formatter* + * @example Input: `{{myMoneyValue, money}}` + * Output: `@[MONEY]{₽100,000,000}` + * @param amount the money amount + * @returns a money formatted string + */ +function i18nMoneyFormatter(amount: any): string { + if (isNaN(Number(amount))) { + console.warn(`i18nMoneyFormatter: value "${amount}" is not a number!`); + } + + return `@[MONEY]{${i18next.t("common:money", { amount })}}`; +} + //#region Exports /** @@ -135,7 +153,7 @@ export async function initI18n(): Promise { i18next.use(new KoreanPostpositionProcessor()); await i18next.init({ fallbackLng: "en", - supportedLngs: ["en", "es", "fr", "it", "de", "zh-CN", "zh-TW", "pt-BR", "ko", "ja", "ca-ES"], + supportedLngs: [ "en", "es", "fr", "it", "de", "zh-CN", "zh-TW", "pt-BR", "ko", "ja", "ca-ES" ], backend: { loadPath(lng: string, [ ns ]: string[]) { let fileName: string; @@ -246,27 +264,13 @@ export async function initI18n(): Promise { interpolation: { escapeValue: false, }, - postProcess: ["korean-postposition"], + postProcess: [ "korean-postposition" ], }); - // Input: {{myMoneyValue, money}} - // Output: @[MONEY]{₽100,000,000} (useful for BBCode coloring of text) - // If you don't want the BBCode tag applied, just use 'number' formatter - i18next.services.formatter?.add("money", (value, lng, options) => { - const numberFormattedString = Intl.NumberFormat(lng, options).format(value); - switch (lng) { - case "ja": - return `@[MONEY]{${numberFormattedString}}円`; - case "de": - case "es": - case "fr": - case "it": - return `@[MONEY]{${numberFormattedString} ₽}`; - default: - // English and other languages that use same format - return `@[MONEY]{₽${numberFormattedString}}`; - } - }); + + if (i18next.services.formatter) { + i18next.services.formatter.add("money", i18nMoneyFormatter); + } await initFonts(localStorage.getItem("prLang") ?? undefined); } diff --git a/src/plugins/vite/vite-minify-json-plugin.ts b/src/plugins/vite/vite-minify-json-plugin.ts index 57130669075..a638271562f 100644 --- a/src/plugins/vite/vite-minify-json-plugin.ts +++ b/src/plugins/vite/vite-minify-json-plugin.ts @@ -41,7 +41,7 @@ export function minifyJsonPlugin(basePath: string | string[], recursive?: boolea }, async closeBundle() { console.log("Minifying JSON files..."); - const basePathes = Array.isArray(basePath) ? basePath : [basePath]; + const basePathes = Array.isArray(basePath) ? basePath : [ basePath ]; basePathes.forEach((basePath) => { const baseDir = path.resolve(buildDir, basePath); diff --git a/src/scene-base.ts b/src/scene-base.ts index 298b8096e54..9af97b8e6d4 100644 --- a/src/scene-base.ts +++ b/src/scene-base.ts @@ -81,7 +81,7 @@ export class SceneBase extends Phaser.Scene { filenames = [ filenames ]; } for (const f of filenames as string[]) { - this.load.audio(folder+key, this.getCachedUrl(`audio/${folder}${f}`)); + this.load.audio(folder + key, this.getCachedUrl(`audio/${folder}${f}`)); } } diff --git a/src/system/achv.ts b/src/system/achv.ts index a355a027093..366813328e2 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -109,7 +109,7 @@ export class DamageAchv extends Achv { damageAmount: integer; constructor(localizationKey: string, name: string, damageAmount: integer, iconImage: string, score: integer) { - super(localizationKey, name, "", iconImage, score, (_scene: BattleScene, args: any[]) => (args[0] as Utils.NumberHolder).value >= this.damageAmount); + super(localizationKey, name, "", iconImage, score, (_scene: BattleScene, args: any[]) => (args[0] instanceof Utils.NumberHolder ? args[0].value : args[0]) >= this.damageAmount); this.damageAmount = damageAmount; } } @@ -118,7 +118,7 @@ export class HealAchv extends Achv { healAmount: integer; constructor(localizationKey: string, name: string, healAmount: integer, iconImage: string, score: integer) { - super(localizationKey, name, "", iconImage, score, (_scene: BattleScene, args: any[]) => (args[0] as Utils.NumberHolder).value >= this.healAmount); + super(localizationKey, name, "", iconImage, score, (_scene: BattleScene, args: any[]) => (args[0] instanceof Utils.NumberHolder ? args[0].value : args[0]) >= this.healAmount); this.healAmount = healAmount; } } @@ -127,7 +127,7 @@ export class LevelAchv extends Achv { level: integer; constructor(localizationKey: string, name: string, level: integer, iconImage: string, score: integer) { - super(localizationKey, name, "", iconImage, score, (scene: BattleScene, args: any[]) => (args[0] as Utils.IntegerHolder).value >= this.level); + super(localizationKey, name, "", iconImage, score, (scene: BattleScene, args: any[]) => (args[0] instanceof Utils.NumberHolder ? args[0].value : args[0]) >= this.level); this.level = level; } } @@ -156,133 +156,133 @@ export function getAchievementDescription(localizationKey: string): string { const genderStr = PlayerGender[genderIndex].toLowerCase(); switch (localizationKey) { - case "10K_MONEY": - return i18next.t("achv:MoneyAchv.description", {context: genderStr, "moneyAmount": achvs._10K_MONEY.moneyAmount.toLocaleString("en-US")}); - case "100K_MONEY": - return i18next.t("achv:MoneyAchv.description", {context: genderStr, "moneyAmount": achvs._100K_MONEY.moneyAmount.toLocaleString("en-US")}); - case "1M_MONEY": - return i18next.t("achv:MoneyAchv.description", {context: genderStr, "moneyAmount": achvs._1M_MONEY.moneyAmount.toLocaleString("en-US")}); - case "10M_MONEY": - return i18next.t("achv:MoneyAchv.description", {context: genderStr, "moneyAmount": achvs._10M_MONEY.moneyAmount.toLocaleString("en-US")}); - case "250_DMG": - return i18next.t("achv:DamageAchv.description", {context: genderStr, "damageAmount": achvs._250_DMG.damageAmount.toLocaleString("en-US")}); - case "1000_DMG": - return i18next.t("achv:DamageAchv.description", {context: genderStr, "damageAmount": achvs._1000_DMG.damageAmount.toLocaleString("en-US")}); - case "2500_DMG": - return i18next.t("achv:DamageAchv.description", {context: genderStr, "damageAmount": achvs._2500_DMG.damageAmount.toLocaleString("en-US")}); - case "10000_DMG": - return i18next.t("achv:DamageAchv.description", {context: genderStr, "damageAmount": achvs._10000_DMG.damageAmount.toLocaleString("en-US")}); - case "250_HEAL": - return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._250_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP))}); - case "1000_HEAL": - return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._1000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP))}); - case "2500_HEAL": - return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._2500_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP))}); - case "10000_HEAL": - return i18next.t("achv:HealAchv.description", {context: genderStr, "healAmount": achvs._10000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP))}); - case "LV_100": - return i18next.t("achv:LevelAchv.description", {context: genderStr, "level": achvs.LV_100.level}); - case "LV_250": - return i18next.t("achv:LevelAchv.description", {context: genderStr, "level": achvs.LV_250.level}); - case "LV_1000": - return i18next.t("achv:LevelAchv.description", {context: genderStr, "level": achvs.LV_1000.level}); - case "10_RIBBONS": - return i18next.t("achv:RibbonAchv.description", {context: genderStr, "ribbonAmount": achvs._10_RIBBONS.ribbonAmount.toLocaleString("en-US")}); - case "25_RIBBONS": - return i18next.t("achv:RibbonAchv.description", {context: genderStr, "ribbonAmount": achvs._25_RIBBONS.ribbonAmount.toLocaleString("en-US")}); - case "50_RIBBONS": - return i18next.t("achv:RibbonAchv.description", {context: genderStr, "ribbonAmount": achvs._50_RIBBONS.ribbonAmount.toLocaleString("en-US")}); - case "75_RIBBONS": - return i18next.t("achv:RibbonAchv.description", {context: genderStr, "ribbonAmount": achvs._75_RIBBONS.ribbonAmount.toLocaleString("en-US")}); - case "100_RIBBONS": - return i18next.t("achv:RibbonAchv.description", {context: genderStr, "ribbonAmount": achvs._100_RIBBONS.ribbonAmount.toLocaleString("en-US")}); - case "TRANSFER_MAX_STAT_STAGE": - return i18next.t("achv:TRANSFER_MAX_STAT_STAGE.description", { context: genderStr }); - case "MAX_FRIENDSHIP": - return i18next.t("achv:MAX_FRIENDSHIP.description", { context: genderStr }); - case "MEGA_EVOLVE": - return i18next.t("achv:MEGA_EVOLVE.description", { context: genderStr }); - case "GIGANTAMAX": - return i18next.t("achv:GIGANTAMAX.description", { context: genderStr }); - case "TERASTALLIZE": - return i18next.t("achv:TERASTALLIZE.description", { context: genderStr }); - case "STELLAR_TERASTALLIZE": - return i18next.t("achv:STELLAR_TERASTALLIZE.description", { context: genderStr }); - case "SPLICE": - return i18next.t("achv:SPLICE.description", { context: genderStr }); - case "MINI_BLACK_HOLE": - return i18next.t("achv:MINI_BLACK_HOLE.description", { context: genderStr }); - case "CATCH_MYTHICAL": - return i18next.t("achv:CATCH_MYTHICAL.description", { context: genderStr }); - case "CATCH_SUB_LEGENDARY": - return i18next.t("achv:CATCH_SUB_LEGENDARY.description", { context: genderStr }); - case "CATCH_LEGENDARY": - return i18next.t("achv:CATCH_LEGENDARY.description", { context: genderStr }); - case "SEE_SHINY": - return i18next.t("achv:SEE_SHINY.description", { context: genderStr }); - case "SHINY_PARTY": - return i18next.t("achv:SHINY_PARTY.description", { context: genderStr }); - case "HATCH_MYTHICAL": - return i18next.t("achv:HATCH_MYTHICAL.description", { context: genderStr }); - case "HATCH_SUB_LEGENDARY": - return i18next.t("achv:HATCH_SUB_LEGENDARY.description", { context: genderStr }); - case "HATCH_LEGENDARY": - return i18next.t("achv:HATCH_LEGENDARY.description", { context: genderStr }); - case "HATCH_SHINY": - return i18next.t("achv:HATCH_SHINY.description", { context: genderStr }); - case "HIDDEN_ABILITY": - return i18next.t("achv:HIDDEN_ABILITY.description", { context: genderStr }); - case "PERFECT_IVS": - return i18next.t("achv:PERFECT_IVS.description", { context: genderStr }); - case "CLASSIC_VICTORY": - return i18next.t("achv:CLASSIC_VICTORY.description", { context: genderStr }); - case "UNEVOLVED_CLASSIC_VICTORY": - return i18next.t("achv:UNEVOLVED_CLASSIC_VICTORY.description", { context: genderStr }); - case "MONO_GEN_ONE": - return i18next.t("achv:MONO_GEN_ONE.description", { context: genderStr }); - case "MONO_GEN_TWO": - return i18next.t("achv:MONO_GEN_TWO.description", { context: genderStr }); - case "MONO_GEN_THREE": - return i18next.t("achv:MONO_GEN_THREE.description", { context: genderStr }); - case "MONO_GEN_FOUR": - return i18next.t("achv:MONO_GEN_FOUR.description", { context: genderStr }); - case "MONO_GEN_FIVE": - return i18next.t("achv:MONO_GEN_FIVE.description", { context: genderStr }); - case "MONO_GEN_SIX": - return i18next.t("achv:MONO_GEN_SIX.description", { context: genderStr }); - case "MONO_GEN_SEVEN": - return i18next.t("achv:MONO_GEN_SEVEN.description", { context: genderStr }); - case "MONO_GEN_EIGHT": - return i18next.t("achv:MONO_GEN_EIGHT.description", { context: genderStr }); - case "MONO_GEN_NINE": - return i18next.t("achv:MONO_GEN_NINE.description", { context: genderStr }); - case "MONO_NORMAL": - case "MONO_FIGHTING": - case "MONO_FLYING": - case "MONO_POISON": - case "MONO_GROUND": - case "MONO_ROCK": - case "MONO_BUG": - case "MONO_GHOST": - case "MONO_STEEL": - case "MONO_FIRE": - case "MONO_WATER": - case "MONO_GRASS": - case "MONO_ELECTRIC": - case "MONO_PSYCHIC": - case "MONO_ICE": - case "MONO_DRAGON": - case "MONO_DARK": - case "MONO_FAIRY": - return i18next.t("achv:MonoType.description", { context: genderStr, "type": i18next.t(`pokemonInfo:Type.${localizationKey.slice(5)}`) }); - case "FRESH_START": - return i18next.t("achv:FRESH_START.description", { context: genderStr }); - case "INVERSE_BATTLE": - return i18next.t("achv:INVERSE_BATTLE.description", { context: genderStr }); - case "BREEDERS_IN_SPACE": - return i18next.t("achv:BREEDERS_IN_SPACE.description", { context: genderStr }); - default: - return ""; + case "10K_MONEY": + return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._10K_MONEY.moneyAmount.toLocaleString("en-US") }); + case "100K_MONEY": + return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._100K_MONEY.moneyAmount.toLocaleString("en-US") }); + case "1M_MONEY": + return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._1M_MONEY.moneyAmount.toLocaleString("en-US") }); + case "10M_MONEY": + return i18next.t("achv:MoneyAchv.description", { context: genderStr, "moneyAmount": achvs._10M_MONEY.moneyAmount.toLocaleString("en-US") }); + case "250_DMG": + return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._250_DMG.damageAmount.toLocaleString("en-US") }); + case "1000_DMG": + return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._1000_DMG.damageAmount.toLocaleString("en-US") }); + case "2500_DMG": + return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._2500_DMG.damageAmount.toLocaleString("en-US") }); + case "10000_DMG": + return i18next.t("achv:DamageAchv.description", { context: genderStr, "damageAmount": achvs._10000_DMG.damageAmount.toLocaleString("en-US") }); + case "250_HEAL": + return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._250_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) }); + case "1000_HEAL": + return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._1000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) }); + case "2500_HEAL": + return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._2500_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) }); + case "10000_HEAL": + return i18next.t("achv:HealAchv.description", { context: genderStr, "healAmount": achvs._10000_HEAL.healAmount.toLocaleString("en-US"), "HP": i18next.t(getShortenedStatKey(Stat.HP)) }); + case "LV_100": + return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_100.level }); + case "LV_250": + return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_250.level }); + case "LV_1000": + return i18next.t("achv:LevelAchv.description", { context: genderStr, "level": achvs.LV_1000.level }); + case "10_RIBBONS": + return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._10_RIBBONS.ribbonAmount.toLocaleString("en-US") }); + case "25_RIBBONS": + return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._25_RIBBONS.ribbonAmount.toLocaleString("en-US") }); + case "50_RIBBONS": + return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._50_RIBBONS.ribbonAmount.toLocaleString("en-US") }); + case "75_RIBBONS": + return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._75_RIBBONS.ribbonAmount.toLocaleString("en-US") }); + case "100_RIBBONS": + return i18next.t("achv:RibbonAchv.description", { context: genderStr, "ribbonAmount": achvs._100_RIBBONS.ribbonAmount.toLocaleString("en-US") }); + case "TRANSFER_MAX_STAT_STAGE": + return i18next.t("achv:TRANSFER_MAX_STAT_STAGE.description", { context: genderStr }); + case "MAX_FRIENDSHIP": + return i18next.t("achv:MAX_FRIENDSHIP.description", { context: genderStr }); + case "MEGA_EVOLVE": + return i18next.t("achv:MEGA_EVOLVE.description", { context: genderStr }); + case "GIGANTAMAX": + return i18next.t("achv:GIGANTAMAX.description", { context: genderStr }); + case "TERASTALLIZE": + return i18next.t("achv:TERASTALLIZE.description", { context: genderStr }); + case "STELLAR_TERASTALLIZE": + return i18next.t("achv:STELLAR_TERASTALLIZE.description", { context: genderStr }); + case "SPLICE": + return i18next.t("achv:SPLICE.description", { context: genderStr }); + case "MINI_BLACK_HOLE": + return i18next.t("achv:MINI_BLACK_HOLE.description", { context: genderStr }); + case "CATCH_MYTHICAL": + return i18next.t("achv:CATCH_MYTHICAL.description", { context: genderStr }); + case "CATCH_SUB_LEGENDARY": + return i18next.t("achv:CATCH_SUB_LEGENDARY.description", { context: genderStr }); + case "CATCH_LEGENDARY": + return i18next.t("achv:CATCH_LEGENDARY.description", { context: genderStr }); + case "SEE_SHINY": + return i18next.t("achv:SEE_SHINY.description", { context: genderStr }); + case "SHINY_PARTY": + return i18next.t("achv:SHINY_PARTY.description", { context: genderStr }); + case "HATCH_MYTHICAL": + return i18next.t("achv:HATCH_MYTHICAL.description", { context: genderStr }); + case "HATCH_SUB_LEGENDARY": + return i18next.t("achv:HATCH_SUB_LEGENDARY.description", { context: genderStr }); + case "HATCH_LEGENDARY": + return i18next.t("achv:HATCH_LEGENDARY.description", { context: genderStr }); + case "HATCH_SHINY": + return i18next.t("achv:HATCH_SHINY.description", { context: genderStr }); + case "HIDDEN_ABILITY": + return i18next.t("achv:HIDDEN_ABILITY.description", { context: genderStr }); + case "PERFECT_IVS": + return i18next.t("achv:PERFECT_IVS.description", { context: genderStr }); + case "CLASSIC_VICTORY": + return i18next.t("achv:CLASSIC_VICTORY.description", { context: genderStr }); + case "UNEVOLVED_CLASSIC_VICTORY": + return i18next.t("achv:UNEVOLVED_CLASSIC_VICTORY.description", { context: genderStr }); + case "MONO_GEN_ONE": + return i18next.t("achv:MONO_GEN_ONE.description", { context: genderStr }); + case "MONO_GEN_TWO": + return i18next.t("achv:MONO_GEN_TWO.description", { context: genderStr }); + case "MONO_GEN_THREE": + return i18next.t("achv:MONO_GEN_THREE.description", { context: genderStr }); + case "MONO_GEN_FOUR": + return i18next.t("achv:MONO_GEN_FOUR.description", { context: genderStr }); + case "MONO_GEN_FIVE": + return i18next.t("achv:MONO_GEN_FIVE.description", { context: genderStr }); + case "MONO_GEN_SIX": + return i18next.t("achv:MONO_GEN_SIX.description", { context: genderStr }); + case "MONO_GEN_SEVEN": + return i18next.t("achv:MONO_GEN_SEVEN.description", { context: genderStr }); + case "MONO_GEN_EIGHT": + return i18next.t("achv:MONO_GEN_EIGHT.description", { context: genderStr }); + case "MONO_GEN_NINE": + return i18next.t("achv:MONO_GEN_NINE.description", { context: genderStr }); + case "MONO_NORMAL": + case "MONO_FIGHTING": + case "MONO_FLYING": + case "MONO_POISON": + case "MONO_GROUND": + case "MONO_ROCK": + case "MONO_BUG": + case "MONO_GHOST": + case "MONO_STEEL": + case "MONO_FIRE": + case "MONO_WATER": + case "MONO_GRASS": + case "MONO_ELECTRIC": + case "MONO_PSYCHIC": + case "MONO_ICE": + case "MONO_DRAGON": + case "MONO_DARK": + case "MONO_FAIRY": + return i18next.t("achv:MonoType.description", { context: genderStr, "type": i18next.t(`pokemonInfo:Type.${localizationKey.slice(5)}`) }); + case "FRESH_START": + return i18next.t("achv:FRESH_START.description", { context: genderStr }); + case "INVERSE_BATTLE": + return i18next.t("achv:INVERSE_BATTLE.description", { context: genderStr }); + case "BREEDERS_IN_SPACE": + return i18next.t("achv:BREEDERS_IN_SPACE.description", { context: genderStr }); + default: + return ""; } } diff --git a/src/system/arena-data.ts b/src/system/arena-data.ts index 5b907805372..ba37de0ed0e 100644 --- a/src/system/arena-data.ts +++ b/src/system/arena-data.ts @@ -1,5 +1,5 @@ import { Arena } from "../field/arena"; -import { ArenaTag } from "../data/arena-tag"; +import { ArenaTag, loadArenaTag } from "../data/arena-tag"; import { Biome } from "#enums/biome"; import { Weather } from "../data/weather"; import { Terrain } from "#app/data/terrain"; @@ -15,6 +15,10 @@ export default class ArenaData { this.biome = sourceArena ? sourceArena.biomeType : source.biome; this.weather = sourceArena ? sourceArena.weather : source.weather ? new Weather(source.weather.weatherType, source.weather.turnsLeft) : null; this.terrain = sourceArena ? sourceArena.terrain : source.terrain ? new Terrain(source.terrain.terrainType, source.terrain.turnsLeft) : null; - this.tags = sourceArena ? sourceArena.tags : []; + this.tags = []; + + if (source.tags) { + this.tags = source.tags.map(t => loadArenaTag(t)); + } } } diff --git a/src/system/egg-data.ts b/src/system/egg-data.ts index 1c9c903688a..aa06316a61f 100644 --- a/src/system/egg-data.ts +++ b/src/system/egg-data.ts @@ -41,7 +41,7 @@ export default class EggData { if (!this.species) { return new Egg({ id: this.id, hatchWaves: this.hatchWaves, sourceType: this.sourceType, timestamp: this.timestamp, tier: Math.floor(this.id / EGG_SEED) }); } else { - return new Egg({id: this.id, tier: this.tier, sourceType: this.sourceType, hatchWaves: this.hatchWaves, + return new Egg({ id: this.id, tier: this.tier, sourceType: this.sourceType, hatchWaves: this.hatchWaves, timestamp: this.timestamp, variantTier: this.variantTier, isShiny: this.isShiny, species: this.species, eggMoveIndex: this.eggMoveIndex, overrideHiddenAbility: this.overrideHiddenAbility }); } diff --git a/src/system/game-data.ts b/src/system/game-data.ts index b597a1b9aad..5f9aad63408 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -31,7 +31,7 @@ import { TrainerVariant } from "#app/field/trainer"; import { Variant } from "#app/data/variant"; import { setSettingGamepad, SettingGamepad, settingGamepadDefaults } from "#app/system/settings/settings-gamepad"; import { setSettingKeyboard, SettingKeyboard } from "#app/system/settings/settings-keyboard"; -import { TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena"; +import { TagAddedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena"; import * as Modifier from "#app/modifier/modifier"; import { StatusEffect } from "#app/data/status-effect"; import ChallengeData from "#app/system/challenge-data"; @@ -43,13 +43,13 @@ import { Species } from "#enums/species"; import { applyChallenges, ChallengeType } from "#app/data/challenge"; import { WeatherType } from "#enums/weather-type"; import { TerrainType } from "#app/data/terrain"; -import { OutdatedPhase } from "#app/phases/outdated-phase"; import { ReloadSessionPhase } from "#app/phases/reload-session-phase"; import { RUN_HISTORY_LIMIT } from "#app/ui/run-history-ui-handler"; -import { applySessionDataPatches, applySettingsDataPatches, applySystemDataPatches } from "#app/system/version-converter"; +import { applySessionVersionMigration, applySystemVersionMigration, applySettingsVersionMigration } from "./version_migration/version_converter"; import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { PokerogueApiClearSessionData } from "#app/@types/pokerogue-api"; +import { ArenaTrapTag } from "#app/data/arena-tag"; export const defaultStarterSpecies: Species[] = [ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, @@ -67,22 +67,22 @@ const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet n export function getDataTypeKey(dataType: GameDataType, slotId: integer = 0): string { switch (dataType) { - case GameDataType.SYSTEM: - return "data"; - case GameDataType.SESSION: - let ret = "sessionData"; - if (slotId) { - ret += slotId; - } - return ret; - case GameDataType.SETTINGS: - return "settings"; - case GameDataType.TUTORIALS: - return "tutorials"; - case GameDataType.SEEN_DIALOGUES: - return "seenDialogues"; - case GameDataType.RUN_HISTORY: - return "runHistoryData"; + case GameDataType.SYSTEM: + return "data"; + case GameDataType.SESSION: + let ret = "sessionData"; + if (slotId) { + ret += slotId; + } + return ret; + case GameDataType.SETTINGS: + return "settings"; + case GameDataType.TUTORIALS: + return "tutorials"; + case GameDataType.SEEN_DIALOGUES: + return "seenDialogues"; + case GameDataType.RUN_HISTORY: + return "runHistoryData"; } } @@ -348,8 +348,8 @@ export class GameData { [VoucherType.GOLDEN]: 0 }; this.eggs = []; - this.eggPity = [0, 0, 0, 0]; - this.unlockPity = [0, 0, 0, 0]; + this.eggPity = [ 0, 0, 0, 0 ]; + this.unlockPity = [ 0, 0, 0, 0 ]; this.initDexData(); this.initStarterData(); } @@ -402,10 +402,7 @@ export class GameData { .then(error => { this.scene.ui.savingIcon.hide(); if (error) { - if (error.startsWith("client version out of date")) { - this.scene.clearPhaseQueue(); - this.scene.unshiftPhase(new OutdatedPhase(this.scene)); - } else if (error.startsWith("session out of date")) { + if (error.startsWith("session out of date")) { this.scene.clearPhaseQueue(); this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); } @@ -481,7 +478,7 @@ export class GameData { localStorage.setItem(lsItemKey, ""); } - applySystemDataPatches(systemData); + applySystemVersionMigration(systemData); this.trainerId = systemData.trainerId; this.secretId = systemData.secretId; @@ -560,8 +557,8 @@ export class GameData { ? systemData.eggs.map(e => e.toEgg()) : []; - this.eggPity = systemData.eggPity ? systemData.eggPity.slice(0) : [0, 0, 0, 0]; - this.unlockPity = systemData.unlockPity ? systemData.unlockPity.slice(0) : [0, 0, 0, 0]; + this.eggPity = systemData.eggPity ? systemData.eggPity.slice(0) : [ 0, 0, 0, 0 ]; + this.unlockPity = systemData.unlockPity ? systemData.unlockPity.slice(0) : [ 0, 0, 0, 0 ]; this.dexData = Object.assign(this.dexData, systemData.dexData); this.consolidateDexData(this.dexData); @@ -856,7 +853,7 @@ export class GameData { const settings = JSON.parse(localStorage.getItem("settings")!); // TODO: is this bang correct? - applySettingsDataPatches(settings); + applySettingsVersionMigration(settings); for (const setting of Object.keys(settings)) { setSetting(this.scene, setting, settings[setting]); @@ -1085,8 +1082,18 @@ export class GameData { scene.arena.terrain = sessionData.arena.terrain; scene.arena.eventTarget.dispatchEvent(new TerrainChangedEvent(TerrainType.NONE, scene.arena.terrain?.terrainType!, scene.arena.terrain?.turnsLeft!)); // TODO: is this bang correct? - // TODO - //scene.arena.tags = sessionData.arena.tags; + + scene.arena.tags = sessionData.arena.tags; + if (scene.arena.tags) { + for (const tag of scene.arena.tags) { + if (tag instanceof ArenaTrapTag) { + const { tagType, side, turnCount, layers, maxLayers } = tag as ArenaTrapTag; + scene.arena.eventTarget.dispatchEvent(new TagAddedEvent(tagType, side, turnCount, layers, maxLayers)); + } else { + scene.arena.eventTarget.dispatchEvent(new TagAddedEvent(tag.tagType, tag.side, tag.turnCount)); + } + } + } for (const modifierData of sessionData.modifiers) { const modifier = modifierData.toModifier(scene, Modifier[modifierData.className]); @@ -1125,10 +1132,16 @@ export class GameData { }); } + /** + * Delete the session data at the given slot when overwriting a save file + * For deleting the session of a finished run, use {@linkcode tryClearSession} + * @param slotId the slot to clear + * @returns Promise with result `true` if the session was deleted successfully, `false` otherwise + */ deleteSession(slotId: integer): Promise { return new Promise(resolve => { if (bypassLogin) { - localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ""}_${loggedInUser?.username}`); + localStorage.removeItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`); return resolve(true); } @@ -1139,7 +1152,7 @@ export class GameData { Utils.apiFetch(`savedata/session/delete?slot=${slotId}&clientSessionId=${clientSessionId}`, true).then(response => { if (response.ok) { loggedInUser!.lastSessionSlot = -1; // TODO: is the bang correct? - localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ""}_${loggedInUser?.username}`); + localStorage.removeItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`); resolve(true); } return response.text(); @@ -1190,27 +1203,29 @@ export class GameData { /** - * Attempt to clear session data. After session data is removed, attempt to update user info so the menu updates + * Attempt to clear session data after the end of a run + * After session data is removed, attempt to update user info so the menu updates + * To delete an unfinished run instead, use {@linkcode deleteSession} */ async tryClearSession(scene: BattleScene, slotId: integer): Promise<[success: boolean, newClear: boolean]> { - let result: [boolean, boolean] = [false, false]; + let result: [boolean, boolean] = [ false, false ]; if (bypassLogin) { localStorage.removeItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`); - result = [true, true]; + result = [ true, true ]; } else { const sessionData = this.getSessionSaveData(scene); const response = await Utils.apiPost(`savedata/session/clear?slot=${slotId}&trainerId=${this.trainerId}&secretId=${this.secretId}&clientSessionId=${clientSessionId}`, JSON.stringify(sessionData), undefined, true); if (response.ok) { loggedInUser!.lastSessionSlot = -1; // TODO: is the bang correct? - localStorage.removeItem(`sessionData${this.scene.sessionSlotId ? this.scene.sessionSlotId : ""}_${loggedInUser?.username}`); + localStorage.removeItem(`sessionData${slotId ? slotId : ""}_${loggedInUser?.username}`); } const jsonResponse: PokerogueApiClearSessionData = await response.json(); if (!jsonResponse.error) { - result = [true, jsonResponse.success ?? false]; + result = [ true, jsonResponse.success ?? false ]; } else { if (jsonResponse && jsonResponse.error?.startsWith("session out of date")) { this.scene.clearPhaseQueue(); @@ -1218,7 +1233,7 @@ export class GameData { } console.error(jsonResponse); - result = [false, false]; + result = [ false, false ]; } } @@ -1294,7 +1309,7 @@ export class GameData { return v; }) as SessionSaveData; - applySessionDataPatches(sessionData); + applySessionVersionMigration(sessionData); return sessionData; } @@ -1335,10 +1350,7 @@ export class GameData { this.scene.ui.savingIcon.hide(); } if (error) { - if (error.startsWith("client version out of date")) { - this.scene.clearPhaseQueue(); - this.scene.unshiftPhase(new OutdatedPhase(this.scene)); - } else if (error.startsWith("session out of date")) { + if (error.startsWith("session out of date")) { this.scene.clearPhaseQueue(); this.scene.unshiftPhase(new ReloadSessionPhase(this.scene)); } @@ -1362,12 +1374,12 @@ export class GameData { const dataKey: string = `${getDataTypeKey(dataType, slotId)}_${loggedInUser?.username}`; const handleData = (dataStr: string) => { switch (dataType) { - case GameDataType.SYSTEM: - dataStr = this.convertSystemDataStr(dataStr, true); - break; + case GameDataType.SYSTEM: + dataStr = this.convertSystemDataStr(dataStr, true); + break; } const encryptedData = AES.encrypt(dataStr, saveKey); - const blob = new Blob([ encryptedData.toString() ], {type: "text/json"}); + const blob = new Blob([ encryptedData.toString() ], { type: "text/json" }); const link = document.createElement("a"); link.href = window.URL.createObjectURL(blob); link.download = `${dataKey}.prsv`; @@ -1422,28 +1434,28 @@ export class GameData { try { dataName = GameDataType[dataType].toLowerCase(); switch (dataType) { - case GameDataType.SYSTEM: - dataStr = this.convertSystemDataStr(dataStr); - const systemData = this.parseSystemData(dataStr); - valid = !!systemData.dexData && !!systemData.timestamp; - break; - case GameDataType.SESSION: - const sessionData = this.parseSessionData(dataStr); - valid = !!sessionData.party && !!sessionData.enemyParty && !!sessionData.timestamp; - break; - case GameDataType.RUN_HISTORY: - const data = JSON.parse(dataStr); - const keys = Object.keys(data); - dataName = i18next.t("menuUiHandler:RUN_HISTORY").toLowerCase(); - keys.forEach((key) => { - const entryKeys = Object.keys(data[key]); - valid = ["isFavorite", "isVictory", "entry"].every(v => entryKeys.includes(v)) && entryKeys.length === 3; - }); - break; - case GameDataType.SETTINGS: - case GameDataType.TUTORIALS: - valid = true; - break; + case GameDataType.SYSTEM: + dataStr = this.convertSystemDataStr(dataStr); + const systemData = this.parseSystemData(dataStr); + valid = !!systemData.dexData && !!systemData.timestamp; + break; + case GameDataType.SESSION: + const sessionData = this.parseSessionData(dataStr); + valid = !!sessionData.party && !!sessionData.enemyParty && !!sessionData.timestamp; + break; + case GameDataType.RUN_HISTORY: + const data = JSON.parse(dataStr); + const keys = Object.keys(data); + dataName = i18next.t("menuUiHandler:RUN_HISTORY").toLowerCase(); + keys.forEach((key) => { + const entryKeys = Object.keys(data[key]); + valid = [ "isFavorite", "isVictory", "entry" ].every(v => entryKeys.includes(v)) && entryKeys.length === 3; + }); + break; + case GameDataType.SETTINGS: + case GameDataType.TUTORIALS: + valid = true; + break; } } catch (ex) { console.error(ex); diff --git a/src/system/settings/settings-gamepad.ts b/src/system/settings/settings-gamepad.ts index 5dd94b780a0..322b2baac9e 100644 --- a/src/system/settings/settings-gamepad.ts +++ b/src/system/settings/settings-gamepad.ts @@ -1,9 +1,9 @@ import BattleScene from "../../battle-scene"; import SettingsGamepadUiHandler from "../../ui/settings/settings-gamepad-ui-handler"; -import {Mode} from "../../ui/ui"; -import {truncateString} from "../../utils"; -import {Button} from "#enums/buttons"; -import {SettingKeyboard} from "#app/system/settings/settings-keyboard"; +import { Mode } from "../../ui/ui"; +import { truncateString } from "../../utils"; +import { Button } from "#enums/buttons"; +import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; export enum SettingGamepad { Controller = "CONTROLLER", @@ -30,25 +30,25 @@ export enum SettingGamepad { const pressAction = "Press action to assign"; export const settingGamepadOptions = { - [SettingGamepad.Controller]: ["Default", "Change"], - [SettingGamepad.Gamepad_Support]: ["Auto", "Disabled"], - [SettingGamepad.Button_Up]: [`KEY ${Button.UP.toString()}`, pressAction], - [SettingGamepad.Button_Down]: [`KEY ${Button.DOWN.toString()}`, pressAction], - [SettingGamepad.Button_Left]: [`KEY ${Button.LEFT.toString()}`, pressAction], - [SettingGamepad.Button_Right]: [`KEY ${Button.RIGHT.toString()}`, pressAction], - [SettingGamepad.Button_Action]: [`KEY ${Button.ACTION.toString()}`, pressAction], - [SettingGamepad.Button_Cancel]: [`KEY ${Button.CANCEL.toString()}`, pressAction], - [SettingGamepad.Button_Menu]: [`KEY ${Button.MENU.toString()}`, pressAction], - [SettingGamepad.Button_Stats]: [`KEY ${Button.STATS.toString()}`, pressAction], - [SettingGamepad.Button_Cycle_Form]: [`KEY ${Button.CYCLE_FORM.toString()}`, pressAction], - [SettingGamepad.Button_Cycle_Shiny]: [`KEY ${Button.CYCLE_SHINY.toString()}`, pressAction], - [SettingGamepad.Button_Cycle_Gender]: [`KEY ${Button.CYCLE_GENDER.toString()}`, pressAction], - [SettingGamepad.Button_Cycle_Ability]: [`KEY ${Button.CYCLE_ABILITY.toString()}`, pressAction], - [SettingGamepad.Button_Cycle_Nature]: [`KEY ${Button.CYCLE_NATURE.toString()}`, pressAction], - [SettingGamepad.Button_Cycle_Variant]: [`KEY ${Button.V.toString()}`, pressAction], - [SettingGamepad.Button_Speed_Up]: [`KEY ${Button.SPEED_UP.toString()}`, pressAction], - [SettingGamepad.Button_Slow_Down]: [`KEY ${Button.SLOW_DOWN.toString()}`, pressAction], - [SettingGamepad.Button_Submit]: [`KEY ${Button.SUBMIT.toString()}`, pressAction], + [SettingGamepad.Controller]: [ "Default", "Change" ], + [SettingGamepad.Gamepad_Support]: [ "Auto", "Disabled" ], + [SettingGamepad.Button_Up]: [ `KEY ${Button.UP.toString()}`, pressAction ], + [SettingGamepad.Button_Down]: [ `KEY ${Button.DOWN.toString()}`, pressAction ], + [SettingGamepad.Button_Left]: [ `KEY ${Button.LEFT.toString()}`, pressAction ], + [SettingGamepad.Button_Right]: [ `KEY ${Button.RIGHT.toString()}`, pressAction ], + [SettingGamepad.Button_Action]: [ `KEY ${Button.ACTION.toString()}`, pressAction ], + [SettingGamepad.Button_Cancel]: [ `KEY ${Button.CANCEL.toString()}`, pressAction ], + [SettingGamepad.Button_Menu]: [ `KEY ${Button.MENU.toString()}`, pressAction ], + [SettingGamepad.Button_Stats]: [ `KEY ${Button.STATS.toString()}`, pressAction ], + [SettingGamepad.Button_Cycle_Form]: [ `KEY ${Button.CYCLE_FORM.toString()}`, pressAction ], + [SettingGamepad.Button_Cycle_Shiny]: [ `KEY ${Button.CYCLE_SHINY.toString()}`, pressAction ], + [SettingGamepad.Button_Cycle_Gender]: [ `KEY ${Button.CYCLE_GENDER.toString()}`, pressAction ], + [SettingGamepad.Button_Cycle_Ability]: [ `KEY ${Button.CYCLE_ABILITY.toString()}`, pressAction ], + [SettingGamepad.Button_Cycle_Nature]: [ `KEY ${Button.CYCLE_NATURE.toString()}`, pressAction ], + [SettingGamepad.Button_Cycle_Variant]: [ `KEY ${Button.V.toString()}`, pressAction ], + [SettingGamepad.Button_Speed_Up]: [ `KEY ${Button.SPEED_UP.toString()}`, pressAction ], + [SettingGamepad.Button_Slow_Down]: [ `KEY ${Button.SLOW_DOWN.toString()}`, pressAction ], + [SettingGamepad.Button_Submit]: [ `KEY ${Button.SUBMIT.toString()}`, pressAction ], }; export const settingGamepadDefaults = { @@ -82,66 +82,66 @@ export const settingGamepadBlackList = [ export function setSettingGamepad(scene: BattleScene, setting: SettingGamepad, value: integer): boolean { switch (setting) { - case SettingGamepad.Gamepad_Support: + case SettingGamepad.Gamepad_Support: // if we change the value of the gamepad support, we call a method in the inputController to // activate or deactivate the controller listener - scene.inputController.setGamepadSupport(settingGamepadOptions[setting][value] !== "Disabled"); - break; - case SettingGamepad.Button_Action: - case SettingGamepad.Button_Cancel: - case SettingGamepad.Button_Menu: - case SettingGamepad.Button_Stats: - case SettingGamepad.Button_Cycle_Shiny: - case SettingGamepad.Button_Cycle_Form: - case SettingGamepad.Button_Cycle_Gender: - case SettingGamepad.Button_Cycle_Ability: - case SettingGamepad.Button_Cycle_Nature: - case SettingGamepad.Button_Cycle_Variant: - case SettingGamepad.Button_Speed_Up: - case SettingGamepad.Button_Slow_Down: - case SettingGamepad.Button_Submit: - if (value) { - if (scene.ui) { - const cancelHandler = (success: boolean = false) : boolean => { - scene.ui.revertMode(); - (scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings(); - return success; - }; - scene.ui.setOverlayMode(Mode.GAMEPAD_BINDING, { - target: setting, - cancelHandler: cancelHandler, - }); + scene.inputController.setGamepadSupport(settingGamepadOptions[setting][value] !== "Disabled"); + break; + case SettingGamepad.Button_Action: + case SettingGamepad.Button_Cancel: + case SettingGamepad.Button_Menu: + case SettingGamepad.Button_Stats: + case SettingGamepad.Button_Cycle_Shiny: + case SettingGamepad.Button_Cycle_Form: + case SettingGamepad.Button_Cycle_Gender: + case SettingGamepad.Button_Cycle_Ability: + case SettingGamepad.Button_Cycle_Nature: + case SettingGamepad.Button_Cycle_Variant: + case SettingGamepad.Button_Speed_Up: + case SettingGamepad.Button_Slow_Down: + case SettingGamepad.Button_Submit: + if (value) { + if (scene.ui) { + const cancelHandler = (success: boolean = false) : boolean => { + scene.ui.revertMode(); + (scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings(); + return success; + }; + scene.ui.setOverlayMode(Mode.GAMEPAD_BINDING, { + target: setting, + cancelHandler: cancelHandler, + }); + } } - } - break; - case SettingGamepad.Controller: - if (value) { - const gp = scene.inputController.getGamepadsName(); - if (scene.ui && gp) { - const cancelHandler = () => { - scene.ui.revertMode(); - (scene.ui.getHandler() as SettingsGamepadUiHandler).setOptionCursor(Object.values(SettingGamepad).indexOf(SettingGamepad.Controller), 0, true); - (scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings(); + break; + case SettingGamepad.Controller: + if (value) { + const gp = scene.inputController.getGamepadsName(); + if (scene.ui && gp) { + const cancelHandler = () => { + scene.ui.revertMode(); + (scene.ui.getHandler() as SettingsGamepadUiHandler).setOptionCursor(Object.values(SettingGamepad).indexOf(SettingGamepad.Controller), 0, true); + (scene.ui.getHandler() as SettingsGamepadUiHandler).updateBindings(); + return false; + }; + const changeGamepadHandler = (gamepad: string) => { + scene.inputController.setChosenGamepad(gamepad); + cancelHandler(); + return true; + }; + scene.ui.setOverlayMode(Mode.OPTION_SELECT, { + options: [ ...gp.map((g: string) => ({ + label: truncateString(g, 30), // Truncate the gamepad name for display + handler: () => changeGamepadHandler(g) + })), { + label: "Cancel", + handler: cancelHandler, + }] + }); return false; - }; - const changeGamepadHandler = (gamepad: string) => { - scene.inputController.setChosenGamepad(gamepad); - cancelHandler(); - return true; - }; - scene.ui.setOverlayMode(Mode.OPTION_SELECT, { - options: [...gp.map((g: string) => ({ - label: truncateString(g, 30), // Truncate the gamepad name for display - handler: () => changeGamepadHandler(g) - })), { - label: "Cancel", - handler: cancelHandler, - }] - }); - return false; + } } - } - break; + break; } return true; diff --git a/src/system/settings/settings-keyboard.ts b/src/system/settings/settings-keyboard.ts index d60af06e12b..97990f61c86 100644 --- a/src/system/settings/settings-keyboard.ts +++ b/src/system/settings/settings-keyboard.ts @@ -1,6 +1,6 @@ -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import BattleScene from "#app/battle-scene"; -import {Mode} from "#app/ui/ui"; +import { Mode } from "#app/ui/ui"; import SettingsKeyboardUiHandler from "#app/ui/settings/settings-keyboard-ui-handler"; import i18next from "i18next"; @@ -46,40 +46,40 @@ const pressAction = i18next.t("settings:pressToBind"); export const settingKeyboardOptions = { // [SettingKeyboard.Default_Layout]: ['Default'], - [SettingKeyboard.Button_Up]: [`KEY ${Button.UP.toString()}`, pressAction], - [SettingKeyboard.Button_Down]: [`KEY ${Button.DOWN.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Up]: [`KEY ${Button.UP.toString()}`, pressAction], - [SettingKeyboard.Button_Left]: [`KEY ${Button.LEFT.toString()}`, pressAction], - [SettingKeyboard.Button_Right]: [`KEY ${Button.RIGHT.toString()}`, pressAction], - [SettingKeyboard.Button_Action]: [`KEY ${Button.ACTION.toString()}`, pressAction], - [SettingKeyboard.Button_Menu]: [`KEY ${Button.MENU.toString()}`, pressAction], - [SettingKeyboard.Button_Submit]: [`KEY ${Button.SUBMIT.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Down]: [`KEY ${Button.DOWN.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Left]: [`KEY ${Button.LEFT.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Right]: [`KEY ${Button.RIGHT.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Action]: [`KEY ${Button.ACTION.toString()}`, pressAction], - [SettingKeyboard.Button_Cancel]: [`KEY ${Button.CANCEL.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Cancel]: [`KEY ${Button.CANCEL.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Menu]: [`KEY ${Button.MENU.toString()}`, pressAction], - [SettingKeyboard.Button_Stats]: [`KEY ${Button.STATS.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Stats]: [`KEY ${Button.STATS.toString()}`, pressAction], - [SettingKeyboard.Button_Cycle_Form]: [`KEY ${Button.CYCLE_FORM.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Cycle_Form]: [`KEY ${Button.CYCLE_FORM.toString()}`, pressAction], - [SettingKeyboard.Button_Cycle_Shiny]: [`KEY ${Button.CYCLE_SHINY.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Cycle_Shiny]: [`KEY ${Button.CYCLE_SHINY.toString()}`, pressAction], - [SettingKeyboard.Button_Cycle_Gender]: [`KEY ${Button.CYCLE_GENDER.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Cycle_Gender]: [`KEY ${Button.CYCLE_GENDER.toString()}`, pressAction], - [SettingKeyboard.Button_Cycle_Ability]: [`KEY ${Button.CYCLE_ABILITY.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Cycle_Ability]: [`KEY ${Button.CYCLE_ABILITY.toString()}`, pressAction], - [SettingKeyboard.Button_Cycle_Nature]: [`KEY ${Button.CYCLE_NATURE.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Cycle_Nature]: [`KEY ${Button.CYCLE_NATURE.toString()}`, pressAction], - [SettingKeyboard.Button_Cycle_Variant]: [`KEY ${Button.V.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Cycle_Variant]: [`KEY ${Button.V.toString()}`, pressAction], - [SettingKeyboard.Button_Speed_Up]: [`KEY ${Button.SPEED_UP.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Speed_Up]: [`KEY ${Button.SPEED_UP.toString()}`, pressAction], - [SettingKeyboard.Button_Slow_Down]: [`KEY ${Button.SLOW_DOWN.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Slow_Down]: [`KEY ${Button.SLOW_DOWN.toString()}`, pressAction], - [SettingKeyboard.Alt_Button_Submit]: [`KEY ${Button.SUBMIT.toString()}`, pressAction], + [SettingKeyboard.Button_Up]: [ `KEY ${Button.UP.toString()}`, pressAction ], + [SettingKeyboard.Button_Down]: [ `KEY ${Button.DOWN.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Up]: [ `KEY ${Button.UP.toString()}`, pressAction ], + [SettingKeyboard.Button_Left]: [ `KEY ${Button.LEFT.toString()}`, pressAction ], + [SettingKeyboard.Button_Right]: [ `KEY ${Button.RIGHT.toString()}`, pressAction ], + [SettingKeyboard.Button_Action]: [ `KEY ${Button.ACTION.toString()}`, pressAction ], + [SettingKeyboard.Button_Menu]: [ `KEY ${Button.MENU.toString()}`, pressAction ], + [SettingKeyboard.Button_Submit]: [ `KEY ${Button.SUBMIT.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Down]: [ `KEY ${Button.DOWN.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Left]: [ `KEY ${Button.LEFT.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Right]: [ `KEY ${Button.RIGHT.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Action]: [ `KEY ${Button.ACTION.toString()}`, pressAction ], + [SettingKeyboard.Button_Cancel]: [ `KEY ${Button.CANCEL.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Cancel]: [ `KEY ${Button.CANCEL.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Menu]: [ `KEY ${Button.MENU.toString()}`, pressAction ], + [SettingKeyboard.Button_Stats]: [ `KEY ${Button.STATS.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Stats]: [ `KEY ${Button.STATS.toString()}`, pressAction ], + [SettingKeyboard.Button_Cycle_Form]: [ `KEY ${Button.CYCLE_FORM.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Cycle_Form]: [ `KEY ${Button.CYCLE_FORM.toString()}`, pressAction ], + [SettingKeyboard.Button_Cycle_Shiny]: [ `KEY ${Button.CYCLE_SHINY.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Cycle_Shiny]: [ `KEY ${Button.CYCLE_SHINY.toString()}`, pressAction ], + [SettingKeyboard.Button_Cycle_Gender]: [ `KEY ${Button.CYCLE_GENDER.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Cycle_Gender]: [ `KEY ${Button.CYCLE_GENDER.toString()}`, pressAction ], + [SettingKeyboard.Button_Cycle_Ability]: [ `KEY ${Button.CYCLE_ABILITY.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Cycle_Ability]: [ `KEY ${Button.CYCLE_ABILITY.toString()}`, pressAction ], + [SettingKeyboard.Button_Cycle_Nature]: [ `KEY ${Button.CYCLE_NATURE.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Cycle_Nature]: [ `KEY ${Button.CYCLE_NATURE.toString()}`, pressAction ], + [SettingKeyboard.Button_Cycle_Variant]: [ `KEY ${Button.V.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Cycle_Variant]: [ `KEY ${Button.V.toString()}`, pressAction ], + [SettingKeyboard.Button_Speed_Up]: [ `KEY ${Button.SPEED_UP.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Speed_Up]: [ `KEY ${Button.SPEED_UP.toString()}`, pressAction ], + [SettingKeyboard.Button_Slow_Down]: [ `KEY ${Button.SLOW_DOWN.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Slow_Down]: [ `KEY ${Button.SLOW_DOWN.toString()}`, pressAction ], + [SettingKeyboard.Alt_Button_Submit]: [ `KEY ${Button.SUBMIT.toString()}`, pressAction ], }; export const settingKeyboardDefaults = { @@ -135,53 +135,53 @@ export const settingKeyboardBlackList = [ export function setSettingKeyboard(scene: BattleScene, setting: SettingKeyboard, value: integer): boolean { switch (setting) { - case SettingKeyboard.Button_Up: - case SettingKeyboard.Button_Down: - case SettingKeyboard.Button_Left: - case SettingKeyboard.Button_Right: - case SettingKeyboard.Button_Action: - case SettingKeyboard.Button_Cancel: - case SettingKeyboard.Button_Menu: - case SettingKeyboard.Button_Stats: - case SettingKeyboard.Button_Cycle_Shiny: - case SettingKeyboard.Button_Cycle_Form: - case SettingKeyboard.Button_Cycle_Gender: - case SettingKeyboard.Button_Cycle_Ability: - case SettingKeyboard.Button_Cycle_Nature: - case SettingKeyboard.Button_Cycle_Variant: - case SettingKeyboard.Button_Speed_Up: - case SettingKeyboard.Button_Slow_Down: - case SettingKeyboard.Alt_Button_Up: - case SettingKeyboard.Alt_Button_Down: - case SettingKeyboard.Alt_Button_Left: - case SettingKeyboard.Alt_Button_Right: - case SettingKeyboard.Alt_Button_Action: - case SettingKeyboard.Alt_Button_Cancel: - case SettingKeyboard.Alt_Button_Menu: - case SettingKeyboard.Alt_Button_Stats: - case SettingKeyboard.Alt_Button_Cycle_Shiny: - case SettingKeyboard.Alt_Button_Cycle_Form: - case SettingKeyboard.Alt_Button_Cycle_Gender: - case SettingKeyboard.Alt_Button_Cycle_Ability: - case SettingKeyboard.Alt_Button_Cycle_Nature: - case SettingKeyboard.Alt_Button_Cycle_Variant: - case SettingKeyboard.Alt_Button_Speed_Up: - case SettingKeyboard.Alt_Button_Slow_Down: - case SettingKeyboard.Alt_Button_Submit: - if (value) { - if (scene.ui) { - const cancelHandler = (success: boolean = false) : boolean => { - scene.ui.revertMode(); - (scene.ui.getHandler() as SettingsKeyboardUiHandler).updateBindings(); - return success; - }; - scene.ui.setOverlayMode(Mode.KEYBOARD_BINDING, { - target: setting, - cancelHandler: cancelHandler, - }); + case SettingKeyboard.Button_Up: + case SettingKeyboard.Button_Down: + case SettingKeyboard.Button_Left: + case SettingKeyboard.Button_Right: + case SettingKeyboard.Button_Action: + case SettingKeyboard.Button_Cancel: + case SettingKeyboard.Button_Menu: + case SettingKeyboard.Button_Stats: + case SettingKeyboard.Button_Cycle_Shiny: + case SettingKeyboard.Button_Cycle_Form: + case SettingKeyboard.Button_Cycle_Gender: + case SettingKeyboard.Button_Cycle_Ability: + case SettingKeyboard.Button_Cycle_Nature: + case SettingKeyboard.Button_Cycle_Variant: + case SettingKeyboard.Button_Speed_Up: + case SettingKeyboard.Button_Slow_Down: + case SettingKeyboard.Alt_Button_Up: + case SettingKeyboard.Alt_Button_Down: + case SettingKeyboard.Alt_Button_Left: + case SettingKeyboard.Alt_Button_Right: + case SettingKeyboard.Alt_Button_Action: + case SettingKeyboard.Alt_Button_Cancel: + case SettingKeyboard.Alt_Button_Menu: + case SettingKeyboard.Alt_Button_Stats: + case SettingKeyboard.Alt_Button_Cycle_Shiny: + case SettingKeyboard.Alt_Button_Cycle_Form: + case SettingKeyboard.Alt_Button_Cycle_Gender: + case SettingKeyboard.Alt_Button_Cycle_Ability: + case SettingKeyboard.Alt_Button_Cycle_Nature: + case SettingKeyboard.Alt_Button_Cycle_Variant: + case SettingKeyboard.Alt_Button_Speed_Up: + case SettingKeyboard.Alt_Button_Slow_Down: + case SettingKeyboard.Alt_Button_Submit: + if (value) { + if (scene.ui) { + const cancelHandler = (success: boolean = false) : boolean => { + scene.ui.revertMode(); + (scene.ui.getHandler() as SettingsKeyboardUiHandler).updateBindings(); + return success; + }; + scene.ui.setOverlayMode(Mode.KEYBOARD_BINDING, { + target: setting, + cancelHandler: cancelHandler, + }); + } } - } - break; + break; // case SettingKeyboard.Default_Layout: // if (value && scene.ui) { // const cancelHandler = () => { diff --git a/src/system/settings/settings.ts b/src/system/settings/settings.ts index 66021845c29..be440d5d93e 100644 --- a/src/system/settings/settings.ts +++ b/src/system/settings/settings.ts @@ -76,16 +76,16 @@ const SHOP_CURSOR_TARGET_OPTIONS: SettingOption[] = [ const shopCursorTargetIndexMap = SHOP_CURSOR_TARGET_OPTIONS.map(option => { switch (option.value) { - case "Rewards": - return ShopCursorTarget.REWARDS; - case "Shop": - return ShopCursorTarget.SHOP; - case "Reroll": - return ShopCursorTarget.REROLL; - case "Check Team": - return ShopCursorTarget.CHECK_TEAM; - default: - throw new Error(`Unknown value: ${option.value}`); + case "Rewards": + return ShopCursorTarget.REWARDS; + case "Shop": + return ShopCursorTarget.SHOP; + case "Reroll": + return ShopCursorTarget.REROLL; + case "Check Team": + return ShopCursorTarget.CHECK_TEAM; + default: + throw new Error(`Unknown value: ${option.value}`); } }); @@ -699,226 +699,226 @@ export function setSetting(scene: BattleScene, setting: string, value: integer): return false; } switch (Setting[index].key) { - case SettingKeys.Game_Speed: - scene.gameSpeed = parseFloat(Setting[index].options[value].value.replace("x", "")); - break; - case SettingKeys.Master_Volume: - scene.masterVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; - scene.updateSoundVolume(); - break; - case SettingKeys.BGM_Volume: - scene.bgmVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; - scene.updateSoundVolume(); - break; - case SettingKeys.Field_Volume: - scene.fieldVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; - scene.updateSoundVolume(); - break; - case SettingKeys.SE_Volume: - scene.seVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; - scene.updateSoundVolume(); - break; - case SettingKeys.UI_Volume: - scene.uiVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; - break; - case SettingKeys.Music_Preference: - scene.musicPreference = value; - break; - case SettingKeys.Damage_Numbers: - scene.damageNumbersMode = value; - break; - case SettingKeys.UI_Theme: - scene.uiTheme = value; - break; - case SettingKeys.Window_Type: - updateWindowType(scene, parseInt(Setting[index].options[value].value)); - break; - case SettingKeys.Tutorials: - scene.enableTutorials = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Move_Info: - scene.enableMoveInfo = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Enable_Retries: - scene.enableRetries = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Hide_IVs: - scene.hideIvs = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Skip_Seen_Dialogues: - scene.skipSeenDialogues = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Egg_Skip: - scene.eggSkipPreference = value; - break; - case SettingKeys.Battle_Style: - scene.battleStyle = value; - break; - case SettingKeys.Show_BGM_Bar: - scene.showBgmBar = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Candy_Upgrade_Notification: - if (scene.candyUpgradeNotification === value) { + case SettingKeys.Game_Speed: + scene.gameSpeed = parseFloat(Setting[index].options[value].value.replace("x", "")); break; - } - scene.candyUpgradeNotification = value; - scene.eventTarget.dispatchEvent(new CandyUpgradeNotificationChangedEvent(value)); - break; - case SettingKeys.Candy_Upgrade_Display: - scene.candyUpgradeDisplay = value; - case SettingKeys.Money_Format: - switch (Setting[index].options[value].value) { - case "Normal": - scene.moneyFormat = MoneyFormat.NORMAL; + case SettingKeys.Master_Volume: + scene.masterVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; + scene.updateSoundVolume(); break; - case "Abbreviated": - scene.moneyFormat = MoneyFormat.ABBREVIATED; + case SettingKeys.BGM_Volume: + scene.bgmVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; + scene.updateSoundVolume(); break; - } - scene.updateMoneyText(false); - break; - case SettingKeys.Sprite_Set: - scene.experimentalSprites = !!value; - if (value) { - scene.initExpSprites(); - } - break; - case SettingKeys.Move_Animations: - scene.moveAnimations = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Show_Moveset_Flyout: - scene.showMovesetFlyout = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Show_Arena_Flyout: - scene.showArenaFlyout = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Show_Time_Of_Day_Widget: - scene.showTimeOfDayWidget = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Time_Of_Day_Animation: - scene.timeOfDayAnimation = Setting[index].options[value].value === "Bounce" ? EaseType.BOUNCE : EaseType.BACK; - break; - case SettingKeys.Show_Stats_on_Level_Up: - scene.showLevelUpStats = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Shop_Cursor_Target: - const selectedValue = shopCursorTargetIndexMap[value]; - scene.shopCursorTarget = selectedValue; - break; - case SettingKeys.EXP_Gains_Speed: - scene.expGainsSpeed = value; - break; - case SettingKeys.EXP_Party_Display: - scene.expParty = value; - break; - case SettingKeys.HP_Bar_Speed: - scene.hpBarSpeed = value; - break; - case SettingKeys.Fusion_Palette_Swaps: - scene.fusionPaletteSwaps = !!value; - break; - case SettingKeys.Player_Gender: - if (scene.gameData) { - const female = Setting[index].options[value].value === "Girl"; - scene.gameData.gender = female ? PlayerGender.FEMALE : PlayerGender.MALE; - scene.trainer.setTexture(scene.trainer.texture.key.replace(female ? "m" : "f", female ? "f" : "m")); - } else { - return false; - } - break; - case SettingKeys.Touch_Controls: - scene.enableTouchControls = Setting[index].options[value].value !== "Disabled" && hasTouchscreen(); - const touchControls = document.getElementById("touchControls"); - if (touchControls) { - touchControls.classList.toggle("visible", scene.enableTouchControls); - } - break; - case SettingKeys.Vibration: - scene.enableVibration = Setting[index].options[value].value !== "Disabled" && hasTouchscreen(); - break; - case SettingKeys.Type_Hints: - scene.typeHints = Setting[index].options[value].value === "On"; - break; - case SettingKeys.Language: - if (value) { - if (scene.ui) { - const cancelHandler = () => { - scene.ui.revertMode(); - (scene.ui.getHandler() as SettingsUiHandler).setOptionCursor(0, 0, true); - }; - const changeLocaleHandler = (locale: string): boolean => { - try { - i18next.changeLanguage(locale); - localStorage.setItem("prLang", locale); - cancelHandler(); - // Reload the whole game to apply the new locale since also some constants are translated - window.location.reload(); - return true; - } catch (error) { - console.error("Error changing locale:", error); - return false; - } - }; - scene.ui.setOverlayMode(Mode.OPTION_SELECT, { - options: [ - { - label: "English", - handler: () => changeLocaleHandler("en") - }, - { - label: "Español", - handler: () => changeLocaleHandler("es") - }, - { - label: "Italiano", - handler: () => changeLocaleHandler("it") - }, - { - label: "Français", - handler: () => changeLocaleHandler("fr") - }, - { - label: "Deutsch", - handler: () => changeLocaleHandler("de") - }, - { - label: "Português (BR)", - handler: () => changeLocaleHandler("pt-BR") - }, - { - label: "简体中文", - handler: () => changeLocaleHandler("zh-CN") - }, - { - label: "繁體中文", - handler: () => changeLocaleHandler("zh-TW") - }, - { - label: "한국어", - handler: () => changeLocaleHandler("ko") - }, - { - label: "日本語", - handler: () => changeLocaleHandler("ja") - }, - // { - // label: "Català", - // handler: () => changeLocaleHandler("ca-ES") - // }, - { - label: i18next.t("settings:back"), - handler: () => cancelHandler() - } - ], - maxOptions: 7 - }); + case SettingKeys.Field_Volume: + scene.fieldVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; + scene.updateSoundVolume(); + break; + case SettingKeys.SE_Volume: + scene.seVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; + scene.updateSoundVolume(); + break; + case SettingKeys.UI_Volume: + scene.uiVolume = value ? parseInt(Setting[index].options[value].value) * 0.01 : 0; + break; + case SettingKeys.Music_Preference: + scene.musicPreference = value; + break; + case SettingKeys.Damage_Numbers: + scene.damageNumbersMode = value; + break; + case SettingKeys.UI_Theme: + scene.uiTheme = value; + break; + case SettingKeys.Window_Type: + updateWindowType(scene, parseInt(Setting[index].options[value].value)); + break; + case SettingKeys.Tutorials: + scene.enableTutorials = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Move_Info: + scene.enableMoveInfo = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Enable_Retries: + scene.enableRetries = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Hide_IVs: + scene.hideIvs = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Skip_Seen_Dialogues: + scene.skipSeenDialogues = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Egg_Skip: + scene.eggSkipPreference = value; + break; + case SettingKeys.Battle_Style: + scene.battleStyle = value; + break; + case SettingKeys.Show_BGM_Bar: + scene.showBgmBar = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Candy_Upgrade_Notification: + if (scene.candyUpgradeNotification === value) { + break; + } + scene.candyUpgradeNotification = value; + scene.eventTarget.dispatchEvent(new CandyUpgradeNotificationChangedEvent(value)); + break; + case SettingKeys.Candy_Upgrade_Display: + scene.candyUpgradeDisplay = value; + case SettingKeys.Money_Format: + switch (Setting[index].options[value].value) { + case "Normal": + scene.moneyFormat = MoneyFormat.NORMAL; + break; + case "Abbreviated": + scene.moneyFormat = MoneyFormat.ABBREVIATED; + break; + } + scene.updateMoneyText(false); + break; + case SettingKeys.Sprite_Set: + scene.experimentalSprites = !!value; + if (value) { + scene.initExpSprites(); + } + break; + case SettingKeys.Move_Animations: + scene.moveAnimations = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Show_Moveset_Flyout: + scene.showMovesetFlyout = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Show_Arena_Flyout: + scene.showArenaFlyout = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Show_Time_Of_Day_Widget: + scene.showTimeOfDayWidget = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Time_Of_Day_Animation: + scene.timeOfDayAnimation = Setting[index].options[value].value === "Bounce" ? EaseType.BOUNCE : EaseType.BACK; + break; + case SettingKeys.Show_Stats_on_Level_Up: + scene.showLevelUpStats = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Shop_Cursor_Target: + const selectedValue = shopCursorTargetIndexMap[value]; + scene.shopCursorTarget = selectedValue; + break; + case SettingKeys.EXP_Gains_Speed: + scene.expGainsSpeed = value; + break; + case SettingKeys.EXP_Party_Display: + scene.expParty = value; + break; + case SettingKeys.HP_Bar_Speed: + scene.hpBarSpeed = value; + break; + case SettingKeys.Fusion_Palette_Swaps: + scene.fusionPaletteSwaps = !!value; + break; + case SettingKeys.Player_Gender: + if (scene.gameData) { + const female = Setting[index].options[value].value === "Girl"; + scene.gameData.gender = female ? PlayerGender.FEMALE : PlayerGender.MALE; + scene.trainer.setTexture(scene.trainer.texture.key.replace(female ? "m" : "f", female ? "f" : "m")); + } else { return false; } - } - break; - case SettingKeys.Shop_Overlay_Opacity: - scene.updateShopOverlayOpacity(parseInt(Setting[index].options[value].value) * .01); - break; + break; + case SettingKeys.Touch_Controls: + scene.enableTouchControls = Setting[index].options[value].value !== "Disabled" && hasTouchscreen(); + const touchControls = document.getElementById("touchControls"); + if (touchControls) { + touchControls.classList.toggle("visible", scene.enableTouchControls); + } + break; + case SettingKeys.Vibration: + scene.enableVibration = Setting[index].options[value].value !== "Disabled" && hasTouchscreen(); + break; + case SettingKeys.Type_Hints: + scene.typeHints = Setting[index].options[value].value === "On"; + break; + case SettingKeys.Language: + if (value) { + if (scene.ui) { + const cancelHandler = () => { + scene.ui.revertMode(); + (scene.ui.getHandler() as SettingsUiHandler).setOptionCursor(0, 0, true); + }; + const changeLocaleHandler = (locale: string): boolean => { + try { + i18next.changeLanguage(locale); + localStorage.setItem("prLang", locale); + cancelHandler(); + // Reload the whole game to apply the new locale since also some constants are translated + window.location.reload(); + return true; + } catch (error) { + console.error("Error changing locale:", error); + return false; + } + }; + scene.ui.setOverlayMode(Mode.OPTION_SELECT, { + options: [ + { + label: "English", + handler: () => changeLocaleHandler("en") + }, + { + label: "Español", + handler: () => changeLocaleHandler("es") + }, + { + label: "Italiano", + handler: () => changeLocaleHandler("it") + }, + { + label: "Français", + handler: () => changeLocaleHandler("fr") + }, + { + label: "Deutsch", + handler: () => changeLocaleHandler("de") + }, + { + label: "Português (BR)", + handler: () => changeLocaleHandler("pt-BR") + }, + { + label: "简体中文", + handler: () => changeLocaleHandler("zh-CN") + }, + { + label: "繁體中文", + handler: () => changeLocaleHandler("zh-TW") + }, + { + label: "한국어", + handler: () => changeLocaleHandler("ko") + }, + { + label: "日本語", + handler: () => changeLocaleHandler("ja") + }, + // { + // label: "Català", + // handler: () => changeLocaleHandler("ca-ES") + // }, + { + label: i18next.t("settings:back"), + handler: () => cancelHandler() + } + ], + maxOptions: 7 + }); + return false; + } + } + break; + case SettingKeys.Shop_Overlay_Opacity: + scene.updateShopOverlayOpacity(parseInt(Setting[index].options[value].value) * .01); + break; } return true; diff --git a/src/system/unlockables.ts b/src/system/unlockables.ts index 983909373fd..0a666e2c755 100644 --- a/src/system/unlockables.ts +++ b/src/system/unlockables.ts @@ -10,13 +10,13 @@ export enum Unlockables { export function getUnlockableName(unlockable: Unlockables) { switch (unlockable) { - case Unlockables.ENDLESS_MODE: - return `${GameMode.getModeName(GameModes.ENDLESS)} Mode`; - case Unlockables.MINI_BLACK_HOLE: - return i18next.t("modifierType:ModifierType.MINI_BLACK_HOLE.name"); - case Unlockables.SPLICED_ENDLESS_MODE: - return `${GameMode.getModeName(GameModes.SPLICED_ENDLESS)} Mode`; - case Unlockables.EVIOLITE: - return i18next.t("modifierType:ModifierType.EVIOLITE.name"); + case Unlockables.ENDLESS_MODE: + return `${GameMode.getModeName(GameModes.ENDLESS)} Mode`; + case Unlockables.MINI_BLACK_HOLE: + return i18next.t("modifierType:ModifierType.MINI_BLACK_HOLE.name"); + case Unlockables.SPLICED_ENDLESS_MODE: + return `${GameMode.getModeName(GameModes.SPLICED_ENDLESS)} Mode`; + case Unlockables.EVIOLITE: + return i18next.t("modifierType:ModifierType.EVIOLITE.name"); } } diff --git a/src/system/version-converter.ts b/src/system/version-converter.ts deleted file mode 100644 index 3a4416a975e..00000000000 --- a/src/system/version-converter.ts +++ /dev/null @@ -1,157 +0,0 @@ -import { allSpecies } from "#app/data/pokemon-species"; -import { AbilityAttr, defaultStarterSpecies, DexAttr, SessionSaveData, SystemSaveData } from "./game-data"; -import { SettingKeys } from "./settings/settings"; - -const LATEST_VERSION = "1.0.5"; - -export function applySessionDataPatches(data: SessionSaveData) { - const curVersion = data.gameVersion; - - // Always sanitize money as a safeguard - data.money = Math.floor(data.money); - - if (curVersion !== LATEST_VERSION) { - switch (curVersion) { - case "1.0.0": - case "1.0.1": - case "1.0.2": - case "1.0.3": - case "1.0.4": - // --- PATCHES --- - - // Fix Battle Items, Vitamins, and Lures - data.modifiers.forEach((m) => { - if (m.className === "PokemonBaseStatModifier") { - m.className = "BaseStatModifier"; - } else if (m.className === "PokemonResetNegativeStatStageModifier") { - m.className = "ResetNegativeStatStageModifier"; - } else if (m.className === "TempBattleStatBoosterModifier") { - // Dire Hit no longer a part of the TempBattleStatBoosterModifierTypeGenerator - if (m.typeId !== "DIRE_HIT") { - m.className = "TempStatStageBoosterModifier"; - m.typeId = "TEMP_STAT_STAGE_BOOSTER"; - - // Migration from TempBattleStat to Stat - const newStat = m.typePregenArgs[0] + 1; - m.typePregenArgs[0] = newStat; - - // From [ stat, battlesLeft ] to [ stat, maxBattles, battleCount ] - m.args = [ newStat, 5, m.args[1] ]; - } else { - m.className = "TempCritBoosterModifier"; - m.typePregenArgs = []; - - // From [ stat, battlesLeft ] to [ maxBattles, battleCount ] - m.args = [ 5, m.args[1] ]; - } - - } else if (m.className === "DoubleBattleChanceBoosterModifier" && m.args.length === 1) { - let maxBattles: number; - switch (m.typeId) { - case "MAX_LURE": - maxBattles = 30; - break; - case "SUPER_LURE": - maxBattles = 15; - break; - default: - maxBattles = 10; - break; - } - - // From [ battlesLeft ] to [ maxBattles, battleCount ] - m.args = [ maxBattles, m.args[0] ]; - } - }); - - data.enemyModifiers.forEach((m) => { - if (m.className === "PokemonBaseStatModifier") { - m.className = "BaseStatModifier"; - } else if (m.className === "PokemonResetNegativeStatStageModifier") { - m.className = "ResetNegativeStatStageModifier"; - } - }); - } - - data.gameVersion = LATEST_VERSION; - } -} - -export function applySystemDataPatches(data: SystemSaveData) { - const curVersion = data.gameVersion; - if (curVersion !== LATEST_VERSION) { - switch (curVersion) { - case "1.0.0": - case "1.0.1": - case "1.0.2": - case "1.0.3": - case "1.0.4": - // --- LEGACY PATCHES --- - if (data.starterData && data.dexData) { - // Migrate ability starter data if empty for caught species - Object.keys(data.starterData).forEach(sd => { - if (data.dexData[sd]?.caughtAttr && (data.starterData[sd] && !data.starterData[sd].abilityAttr)) { - data.starterData[sd].abilityAttr = 1; - } - }); - } - - // Fix Legendary Stats - if (data.gameStats && (data.gameStats.legendaryPokemonCaught !== undefined && data.gameStats.subLegendaryPokemonCaught === undefined)) { - data.gameStats.subLegendaryPokemonSeen = 0; - data.gameStats.subLegendaryPokemonCaught = 0; - data.gameStats.subLegendaryPokemonHatched = 0; - allSpecies.filter(s => s.subLegendary).forEach(s => { - const dexEntry = data.dexData[s.speciesId]; - data.gameStats.subLegendaryPokemonSeen += dexEntry.seenCount; - data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen - dexEntry.seenCount, 0); - data.gameStats.subLegendaryPokemonCaught += dexEntry.caughtCount; - data.gameStats.legendaryPokemonCaught = Math.max(data.gameStats.legendaryPokemonCaught - dexEntry.caughtCount, 0); - data.gameStats.subLegendaryPokemonHatched += dexEntry.hatchedCount; - data.gameStats.legendaryPokemonHatched = Math.max(data.gameStats.legendaryPokemonHatched - dexEntry.hatchedCount, 0); - }); - data.gameStats.subLegendaryPokemonSeen = Math.max(data.gameStats.subLegendaryPokemonSeen, data.gameStats.subLegendaryPokemonCaught); - data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen, data.gameStats.legendaryPokemonCaught); - data.gameStats.mythicalPokemonSeen = Math.max(data.gameStats.mythicalPokemonSeen, data.gameStats.mythicalPokemonCaught); - } - - // --- PATCHES --- - - // Fix Starter Data - if (data.starterData && data.dexData) { - for (const starterId of defaultStarterSpecies) { - if (data.starterData[starterId]?.abilityAttr) { - data.starterData[starterId].abilityAttr |= AbilityAttr.ABILITY_1; - } - if (data.dexData[starterId]?.caughtAttr) { - data.dexData[starterId].caughtAttr |= DexAttr.FEMALE; - } - } - } - } - - data.gameVersion = LATEST_VERSION; - } -} - -export function applySettingsDataPatches(settings: Object) { - const curVersion = settings.hasOwnProperty("gameVersion") ? settings["gameVersion"] : "1.0.0"; - if (curVersion !== LATEST_VERSION) { - switch (curVersion) { - case "1.0.0": - case "1.0.1": - case "1.0.2": - case "1.0.3": - case "1.0.4": - // --- PATCHES --- - - // Fix Reward Cursor Target - if (settings.hasOwnProperty("REROLL_TARGET") && !settings.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) { - settings[SettingKeys.Shop_Cursor_Target] = settings["REROLL_TARGET"]; - delete settings["REROLL_TARGET"]; - localStorage.setItem("settings", JSON.stringify(settings)); - } - } - // Note that the current game version will be written at `saveSettings` - } -} diff --git a/src/system/version_migration/version_converter.ts b/src/system/version_migration/version_converter.ts new file mode 100644 index 00000000000..f93e09b7a90 --- /dev/null +++ b/src/system/version_migration/version_converter.ts @@ -0,0 +1,182 @@ +import { SessionSaveData, SystemSaveData } from "../game-data"; +import { version } from "../../../package.json"; + +// --- v1.0.4 (and below) PATCHES --- // +import * as v1_0_4 from "./versions/v1_0_4"; + +const LATEST_VERSION = version.split(".").map(value => parseInt(value)); + +/** + * Converts incoming {@linkcode SystemSaveData} that has a version below the + * current version number listed in `package.json`. + * + * Note that no transforms act on the {@linkcode data} if its version matches + * the current version or if there are no migrations made between its version up + * to the current version. + * @param data {@linkcode SystemSaveData} + * @see {@link SystemVersionConverter} + */ +export function applySystemVersionMigration(data: SystemSaveData) { + const curVersion = data.gameVersion.split(".").map(value => parseInt(value)); + + if (!curVersion.every((value, index) => value === LATEST_VERSION[index])) { + const converter = new SystemVersionConverter(); + converter.applyStaticPreprocessors(data); + converter.applyMigration(data, curVersion); + } +} + +/** + * Converts incoming {@linkcode SessionSavaData} that has a version below the + * current version number listed in `package.json`. + * + * Note that no transforms act on the {@linkcode data} if its version matches + * the current version or if there are no migrations made between its version up + * to the current version. + * @param data {@linkcode SessionSaveData} + * @see {@link SessionVersionConverter} + */ +export function applySessionVersionMigration(data: SessionSaveData) { + const curVersion = data.gameVersion.split(".").map(value => parseInt(value)); + + if (!curVersion.every((value, index) => value === LATEST_VERSION[index])) { + const converter = new SessionVersionConverter(); + converter.applyStaticPreprocessors(data); + converter.applyMigration(data, curVersion); + } +} + +/** + * Converts incoming settings data that has a version below the + * current version number listed in `package.json`. + * + * Note that no transforms act on the {@linkcode data} if its version matches + * the current version or if there are no migrations made between its version up + * to the current version. + * @param data Settings data object + * @see {@link SettingsVersionConverter} + */ +export function applySettingsVersionMigration(data: Object) { + const gameVersion: string = data.hasOwnProperty("gameVersion") ? data["gameVersion"] : "1.0.0"; + const curVersion = gameVersion.split(".").map(value => parseInt(value)); + + if (!curVersion.every((value, index) => value === LATEST_VERSION[index])) { + const converter = new SettingsVersionConverter(); + converter.applyStaticPreprocessors(data); + converter.applyMigration(data, curVersion); + } +} + +/** + * Abstract class encapsulating the logic for migrating data from a given version up to + * the current version listed in `package.json`. + * + * Note that, for any version converter, the corresponding `applyMigration` + * function would only need to be changed once when the first migration for a + * given version is introduced. Similarly, a version file (within the `versions` + * folder) would only need to be created for a version once with the appropriate + * array nomenclature. + */ +abstract class VersionConverter { + /** + * Iterates through an array of designated migration functions that are each + * called one by one to transform the data. + * @param data The data to be operated on + * @param migrationArr An array of functions that will transform the incoming data + */ + callMigrators(data: any, migrationArr: readonly any[]) { + for (const migrate of migrationArr) { + migrate(data); + } + } + + /** + * Applies any version-agnostic data sanitation as defined within the function + * body. + * @param data The data to be operated on + */ + applyStaticPreprocessors(_data: any): void { + } + + /** + * Uses the current version the incoming data to determine the starting point + * of the migration which will cascade up to the latest version, calling the + * necessary migration functions in the process. + * @param data The data to be operated on + * @param curVersion [0] Current major version + * [1] Current minor version + * [2] Current patch version + */ + abstract applyMigration(data: any, curVersion: number[]): void; +} + +/** + * Class encapsulating the logic for migrating {@linkcode SessionSaveData} from + * a given version up to the current version listed in `package.json`. + * @extends VersionConverter + */ +class SessionVersionConverter extends VersionConverter { + override applyStaticPreprocessors(data: SessionSaveData): void { + // Always sanitize money as a safeguard + data.money = Math.floor(data.money); + } + + override applyMigration(data: SessionSaveData, curVersion: number[]): void { + const [ curMajor, curMinor, curPatch ] = curVersion; + + if (curMajor === 1) { + if (curMinor === 0) { + if (curPatch <= 4) { + console.log("Applying v1.0.4 session data migration!"); + this.callMigrators(data, v1_0_4.sessionMigrators); + } + } + } + + console.log(`Session data successfully migrated to v${version}!`); + } +} + +/** + * Class encapsulating the logic for migrating {@linkcode SystemSaveData} from + * a given version up to the current version listed in `package.json`. + * @extends VersionConverter + */ +class SystemVersionConverter extends VersionConverter { + override applyMigration(data: SystemSaveData, curVersion: number[]): void { + const [ curMajor, curMinor, curPatch ] = curVersion; + + if (curMajor === 1) { + if (curMinor === 0) { + if (curPatch <= 4) { + console.log("Applying v1.0.4 system data migraton!"); + this.callMigrators(data, v1_0_4.systemMigrators); + } + } + } + + console.log(`System data successfully migrated to v${version}!`); + } +} + +/** + * Class encapsulating the logic for migrating settings data from + * a given version up to the current version listed in `package.json`. + * @extends VersionConverter + */ +class SettingsVersionConverter extends VersionConverter { + override applyMigration(data: Object, curVersion: number[]): void { + const [ curMajor, curMinor, curPatch ] = curVersion; + + if (curMajor === 1) { + if (curMinor === 0) { + if (curPatch <= 4) { + console.log("Applying v1.0.4 settings data migraton!"); + this.callMigrators(data, v1_0_4.settingsMigrators); + } + } + } + + console.log(`System data successfully migrated to v${version}!`); + } +} diff --git a/src/system/version_migration/versions/v1_0_4.ts b/src/system/version_migration/versions/v1_0_4.ts new file mode 100644 index 00000000000..f16b6bcb6bb --- /dev/null +++ b/src/system/version_migration/versions/v1_0_4.ts @@ -0,0 +1,135 @@ +import { SettingKeys } from "../../settings/settings"; +import { AbilityAttr, defaultStarterSpecies, DexAttr, SystemSaveData, SessionSaveData } from "../../game-data"; +import { allSpecies } from "../../../data/pokemon-species"; + +export const systemMigrators = [ + /** + * Migrate ability starter data if empty for caught species. + * @param data {@linkcode SystemSaveData} + */ + function migrateAbilityData(data: SystemSaveData) { + if (data.starterData && data.dexData) { + Object.keys(data.starterData).forEach(sd => { + if (data.dexData[sd]?.caughtAttr && (data.starterData[sd] && !data.starterData[sd].abilityAttr)) { + data.starterData[sd].abilityAttr = 1; + } + }); + } + }, + + /** + * Populate legendary Pokémon statistics if they are missing. + * @param data {@linkcode SystemSaveData} + */ + function fixLegendaryStats(data: SystemSaveData) { + if (data.gameStats && (data.gameStats.legendaryPokemonCaught !== undefined && data.gameStats.subLegendaryPokemonCaught === undefined)) { + data.gameStats.subLegendaryPokemonSeen = 0; + data.gameStats.subLegendaryPokemonCaught = 0; + data.gameStats.subLegendaryPokemonHatched = 0; + allSpecies.filter(s => s.subLegendary).forEach(s => { + const dexEntry = data.dexData[s.speciesId]; + data.gameStats.subLegendaryPokemonSeen += dexEntry.seenCount; + data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen - dexEntry.seenCount, 0); + data.gameStats.subLegendaryPokemonCaught += dexEntry.caughtCount; + data.gameStats.legendaryPokemonCaught = Math.max(data.gameStats.legendaryPokemonCaught - dexEntry.caughtCount, 0); + data.gameStats.subLegendaryPokemonHatched += dexEntry.hatchedCount; + data.gameStats.legendaryPokemonHatched = Math.max(data.gameStats.legendaryPokemonHatched - dexEntry.hatchedCount, 0); + }); + data.gameStats.subLegendaryPokemonSeen = Math.max(data.gameStats.subLegendaryPokemonSeen, data.gameStats.subLegendaryPokemonCaught); + data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen, data.gameStats.legendaryPokemonCaught); + data.gameStats.mythicalPokemonSeen = Math.max(data.gameStats.mythicalPokemonSeen, data.gameStats.mythicalPokemonCaught); + } + }, + + /** + * Unlock all starters' first ability and female gender option. + * @param data {@linkcode SystemSaveData} + */ + function fixStarterData(data: SystemSaveData) { + for (const starterId of defaultStarterSpecies) { + if (data.starterData[starterId]?.abilityAttr) { + data.starterData[starterId].abilityAttr |= AbilityAttr.ABILITY_1; + } + if (data.dexData[starterId]?.caughtAttr) { + data.dexData[starterId].caughtAttr |= DexAttr.FEMALE; + } + } + } +] as const; + +export const settingsMigrators = [ + /** + * Migrate from "REROLL_TARGET" property to {@linkcode + * SettingKeys.Shop_Cursor_Target}. + * @param data the `settings` object + */ + function fixRerollTarget(data: Object) { + if (data.hasOwnProperty("REROLL_TARGET") && !data.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) { + data[SettingKeys.Shop_Cursor_Target] = data["REROLL_TARGET"]; + delete data["REROLL_TARGET"]; + localStorage.setItem("settings", JSON.stringify(data)); + } + } +] as const; + +export const sessionMigrators = [ + /** + * Converts old lapsing modifiers (battle items, lures, and Dire Hit) and + * other miscellaneous modifiers (vitamins, White Herb) to any new class + * names and/or change in reload arguments. + * @param data {@linkcode SessionSaveData} + */ + function migrateModifiers(data: SessionSaveData) { + data.modifiers.forEach((m) => { + if (m.className === "PokemonBaseStatModifier") { + m.className = "BaseStatModifier"; + } else if (m.className === "PokemonResetNegativeStatStageModifier") { + m.className = "ResetNegativeStatStageModifier"; + } else if (m.className === "TempBattleStatBoosterModifier") { + const maxBattles = 5; + // Dire Hit no longer a part of the TempBattleStatBoosterModifierTypeGenerator + if (m.typeId !== "DIRE_HIT") { + m.className = "TempStatStageBoosterModifier"; + m.typeId = "TEMP_STAT_STAGE_BOOSTER"; + + // Migration from TempBattleStat to Stat + const newStat = m.typePregenArgs[0] + 1; + m.typePregenArgs[0] = newStat; + + // From [ stat, battlesLeft ] to [ stat, maxBattles, battleCount ] + m.args = [ newStat, maxBattles, Math.min(m.args[1], maxBattles) ]; + } else { + m.className = "TempCritBoosterModifier"; + m.typePregenArgs = []; + + // From [ stat, battlesLeft ] to [ maxBattles, battleCount ] + m.args = [ maxBattles, Math.min(m.args[1], maxBattles) ]; + } + } else if (m.className === "DoubleBattleChanceBoosterModifier" && m.args.length === 1) { + let maxBattles: number; + switch (m.typeId) { + case "MAX_LURE": + maxBattles = 30; + break; + case "SUPER_LURE": + maxBattles = 15; + break; + default: + maxBattles = 10; + break; + } + + // From [ battlesLeft ] to [ maxBattles, battleCount ] + m.args = [ maxBattles, Math.min(m.args[0], maxBattles) ]; + } + }); + + data.enemyModifiers.forEach((m) => { + if (m.className === "PokemonBaseStatModifier") { + m.className = "BaseStatModifier"; + } else if (m.className === "PokemonResetNegativeStatStageModifier") { + m.className = "ResetNegativeStatStageModifier"; + } + }); + } +] as const; diff --git a/src/system/voucher.ts b/src/system/voucher.ts index 06edfe5c6a6..b38fd528c9f 100644 --- a/src/system/voucher.ts +++ b/src/system/voucher.ts @@ -45,41 +45,41 @@ export class Voucher { getTier(): AchvTier { switch (this.voucherType) { - case VoucherType.REGULAR: - return AchvTier.COMMON; - case VoucherType.PLUS: - return AchvTier.GREAT; - case VoucherType.PREMIUM: - return AchvTier.ULTRA; - case VoucherType.GOLDEN: - return AchvTier.ROGUE; + case VoucherType.REGULAR: + return AchvTier.COMMON; + case VoucherType.PLUS: + return AchvTier.GREAT; + case VoucherType.PREMIUM: + return AchvTier.ULTRA; + case VoucherType.GOLDEN: + return AchvTier.ROGUE; } } } export function getVoucherTypeName(voucherType: VoucherType): string { switch (voucherType) { - case VoucherType.REGULAR: - return i18next.t("voucher:eggVoucher"); - case VoucherType.PLUS: - return i18next.t("voucher:eggVoucherPlus"); - case VoucherType.PREMIUM: - return i18next.t("voucher:eggVoucherPremium"); - case VoucherType.GOLDEN: - return i18next.t("voucher:eggVoucherGold"); + case VoucherType.REGULAR: + return i18next.t("voucher:eggVoucher"); + case VoucherType.PLUS: + return i18next.t("voucher:eggVoucherPlus"); + case VoucherType.PREMIUM: + return i18next.t("voucher:eggVoucherPremium"); + case VoucherType.GOLDEN: + return i18next.t("voucher:eggVoucherGold"); } } export function getVoucherTypeIcon(voucherType: VoucherType): string { switch (voucherType) { - case VoucherType.REGULAR: - return "coupon"; - case VoucherType.PLUS: - return "pair_of_tickets"; - case VoucherType.PREMIUM: - return "mystic_ticket"; - case VoucherType.GOLDEN: - return "golden_mystic_ticket"; + case VoucherType.REGULAR: + return "coupon"; + case VoucherType.PLUS: + return "pair_of_tickets"; + case VoucherType.PREMIUM: + return "mystic_ticket"; + case VoucherType.GOLDEN: + return "golden_mystic_ticket"; } } @@ -90,7 +90,7 @@ export interface Vouchers { export const vouchers: Vouchers = {}; export function initVouchers() { - for (const achv of [achvs.CLASSIC_VICTORY]) { + for (const achv of [ achvs.CLASSIC_VICTORY ]) { const voucherType = achv.score >= 150 ? VoucherType.GOLDEN : achv.score >= 100 diff --git a/src/test/abilities/ability_duplication.test.ts b/src/test/abilities/ability_duplication.test.ts new file mode 100644 index 00000000000..f9122b3259c --- /dev/null +++ b/src/test/abilities/ability_duplication.test.ts @@ -0,0 +1,58 @@ +import { Stat } from "#app/enums/stat"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest"; + +describe("Ability Duplication", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([ Moves.SPLASH ]) + .battleType("single") + .ability(Abilities.HUGE_POWER) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("huge power should only be applied once if both normal and passive", async () => { + game.override.passiveAbility(Abilities.HUGE_POWER); + + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + const [ magikarp ] = game.scene.getPlayerField(); + const magikarpAttack = magikarp.getEffectiveStat(Stat.ATK); + + magikarp.summonData.abilitySuppressed = true; + + expect(magikarp.getEffectiveStat(Stat.ATK)).toBe(magikarpAttack / 2); + }); + + it("huge power should stack with pure power", async () => { + game.override.passiveAbility(Abilities.PURE_POWER); + + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + const [ magikarp ] = game.scene.getPlayerField(); + const magikarpAttack = magikarp.getEffectiveStat(Stat.ATK); + + magikarp.summonData.abilitySuppressed = true; + + expect(magikarp.getEffectiveStat(Stat.ATK)).toBe(magikarpAttack / 4); + }); +}); diff --git a/src/test/abilities/ability_timing.test.ts b/src/test/abilities/ability_timing.test.ts index 16437df06c9..e3264c2c1a8 100644 --- a/src/test/abilities/ability_timing.test.ts +++ b/src/test/abilities/ability_timing.test.ts @@ -1,13 +1,13 @@ import { BattleStyle } from "#app/enums/battle-style"; import { CommandPhase } from "#app/phases/command-phase"; import { TurnInitPhase } from "#app/phases/turn-init-phase"; -import i18next, { initI18n } from "#app/plugins/i18n"; +import i18next from "#app/plugins/i18n"; import { Mode } from "#app/ui/ui"; import { Abilities } from "#enums/abilities"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; describe("Ability Timing", () => { @@ -32,13 +32,12 @@ describe("Ability Timing", () => { .enemySpecies(Species.MAGIKARP) .enemyAbility(Abilities.INTIMIDATE) .ability(Abilities.BALL_FETCH); + vi.spyOn(i18next, "t"); }); it("should trigger after switch check", async () => { - initI18n(); - i18next.changeLanguage("en"); game.settings.battleStyle = BattleStyle.SWITCH; - await game.classicMode.runToSummon([Species.EEVEE, Species.FEEBAS]); + await game.classicMode.runToSummon([ Species.EEVEE, Species.FEEBAS ]); game.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => { game.setMode(Mode.MESSAGE); @@ -46,7 +45,6 @@ describe("Ability Timing", () => { }, () => game.isCurrentPhase(CommandPhase) || game.isCurrentPhase(TurnInitPhase)); await game.phaseInterceptor.to("MessagePhase"); - const message = game.textInterceptor.getLatestMessage(); - expect(message).toContain("battle:statFell"); + expect(i18next.t).toHaveBeenCalledWith("battle:statFell", expect.objectContaining({ count: 1 })); }, 5000); }); diff --git a/src/test/abilities/aroma_veil.test.ts b/src/test/abilities/aroma_veil.test.ts index b70308a5d60..4284eb43a75 100644 --- a/src/test/abilities/aroma_veil.test.ts +++ b/src/test/abilities/aroma_veil.test.ts @@ -27,14 +27,14 @@ describe("Moves - Aroma Veil", () => { game.override .battleType("double") .enemyAbility(Abilities.BALL_FETCH) - .enemyMoveset([Moves.HEAL_BLOCK, Moves.IMPRISON, Moves.SPLASH]) + .enemyMoveset([ Moves.HEAL_BLOCK, Moves.IMPRISON, Moves.SPLASH ]) .enemySpecies(Species.SHUCKLE) .ability(Abilities.AROMA_VEIL) - .moveset([Moves.GROWL]); + .moveset([ Moves.GROWL ]); }); it("Aroma Veil protects the Pokemon's side against most Move Restriction Battler Tags", async () => { - await game.classicMode.startBattle([Species.REGIELEKI, Species.BULBASAUR]); + await game.classicMode.startBattle([ Species.REGIELEKI, Species.BULBASAUR ]); const party = game.scene.getParty()! as PlayerPokemon[]; @@ -48,7 +48,7 @@ describe("Moves - Aroma Veil", () => { }); it("Aroma Veil does not protect against Imprison", async () => { - await game.classicMode.startBattle([Species.REGIELEKI, Species.BULBASAUR]); + await game.classicMode.startBattle([ Species.REGIELEKI, Species.BULBASAUR ]); const party = game.scene.getParty()! as PlayerPokemon[]; diff --git a/src/test/abilities/aura_break.test.ts b/src/test/abilities/aura_break.test.ts index 422ac5178c1..137688d1f22 100644 --- a/src/test/abilities/aura_break.test.ts +++ b/src/test/abilities/aura_break.test.ts @@ -25,7 +25,7 @@ describe("Abilities - Aura Break", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("single"); - game.override.moveset([Moves.MOONBLAST, Moves.DARK_PULSE, Moves.MOONBLAST, Moves.DARK_PULSE]); + game.override.moveset([ Moves.MOONBLAST, Moves.DARK_PULSE, Moves.MOONBLAST, Moves.DARK_PULSE ]); game.override.enemyMoveset(Moves.SPLASH); game.override.enemyAbility(Abilities.AURA_BREAK); game.override.enemySpecies(Species.SHUCKLE); @@ -38,7 +38,7 @@ describe("Abilities - Aura Break", () => { game.override.ability(Abilities.FAIRY_AURA); vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); game.move.select(Moves.MOONBLAST); await game.phaseInterceptor.to("MoveEffectPhase"); @@ -52,7 +52,7 @@ describe("Abilities - Aura Break", () => { game.override.ability(Abilities.DARK_AURA); vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); game.move.select(Moves.DARK_PULSE); await game.phaseInterceptor.to("MoveEffectPhase"); @@ -66,7 +66,7 @@ describe("Abilities - Aura Break", () => { game.override.ability(Abilities.BALL_FETCH); vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); game.move.select(Moves.MOONBLAST); await game.phaseInterceptor.to("MoveEffectPhase"); diff --git a/src/test/abilities/battery.test.ts b/src/test/abilities/battery.test.ts index cd02ed0c4eb..8abeca287f7 100644 --- a/src/test/abilities/battery.test.ts +++ b/src/test/abilities/battery.test.ts @@ -29,7 +29,7 @@ describe("Abilities - Battery", () => { game.override.battleType("double"); game.override.enemySpecies(Species.SHUCKLE); game.override.enemyAbility(Abilities.BALL_FETCH); - game.override.moveset([Moves.TACKLE, Moves.BREAKING_SWIPE, Moves.SPLASH, Moves.DAZZLING_GLEAM]); + game.override.moveset([ Moves.TACKLE, Moves.BREAKING_SWIPE, Moves.SPLASH, Moves.DAZZLING_GLEAM ]); game.override.enemyMoveset(Moves.SPLASH); }); @@ -39,7 +39,7 @@ describe("Abilities - Battery", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.startBattle([Species.PIKACHU, Species.CHARJABUG]); + await game.startBattle([ Species.PIKACHU, Species.CHARJABUG ]); game.move.select(Moves.DAZZLING_GLEAM); game.move.select(Moves.SPLASH, 1); @@ -54,7 +54,7 @@ describe("Abilities - Battery", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.startBattle([Species.PIKACHU, Species.CHARJABUG]); + await game.startBattle([ Species.PIKACHU, Species.CHARJABUG ]); game.move.select(Moves.BREAKING_SWIPE); game.move.select(Moves.SPLASH, 1); @@ -69,7 +69,7 @@ describe("Abilities - Battery", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.startBattle([Species.CHARJABUG, Species.PIKACHU]); + await game.startBattle([ Species.CHARJABUG, Species.PIKACHU ]); game.move.select(Moves.DAZZLING_GLEAM); game.move.select(Moves.SPLASH, 1); diff --git a/src/test/abilities/battle_bond.test.ts b/src/test/abilities/battle_bond.test.ts index 4882001cc8d..283fb0d0f14 100644 --- a/src/test/abilities/battle_bond.test.ts +++ b/src/test/abilities/battle_bond.test.ts @@ -1,18 +1,19 @@ +import { allMoves, MultiHitAttr, MultiHitType } from "#app/data/move"; import { Status, StatusEffect } from "#app/data/status-effect"; -import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; -import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; describe("Abilities - BATTLE BOND", () => { let phaserGame: Phaser.Game; let game: GameManager; + const baseForm = 1; + const ashForm = 2; + beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -25,40 +26,68 @@ describe("Abilities - BATTLE BOND", () => { beforeEach(() => { game = new GameManager(phaserGame); - const moveToUse = Moves.SPLASH; - game.override.battleType("single"); - game.override.ability(Abilities.BATTLE_BOND); - game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.battleType("single") + .startingWave(4) // Leads to arena reset on Wave 5 trainer battle + .ability(Abilities.BATTLE_BOND) + .starterForms({ [Species.GRENINJA]: ashForm, }) + .moveset([ Moves.SPLASH, Moves.WATER_SHURIKEN ]) + .enemySpecies(Species.BULBASAUR) + .enemyMoveset(Moves.SPLASH) + .startingLevel(100) // Avoid levelling up + .enemyLevel(1000); // Avoid opponent dying before `doKillOpponents()` }); - test( - "check if fainted pokemon switches to base form on arena reset", - async () => { - const baseForm = 1; - const ashForm = 2; - game.override.startingWave(4); - game.override.starterForms({ - [Species.GRENINJA]: ashForm, - }); + it("check if fainted pokemon switches to base form on arena reset", async () => { + await game.classicMode.startBattle([ Species.MAGIKARP, Species.GRENINJA ]); - await game.startBattle([Species.MAGIKARP, Species.GRENINJA]); + const greninja = game.scene.getParty()[1]; + expect(greninja.formIndex).toBe(ashForm); - const greninja = game.scene.getParty().find((p) => p.species.speciesId === Species.GRENINJA); - expect(greninja).toBeDefined(); - expect(greninja!.formIndex).toBe(ashForm); + greninja.hp = 0; + greninja.status = new Status(StatusEffect.FAINT); + expect(greninja.isFainted()).toBe(true); - greninja!.hp = 0; - greninja!.status = new Status(StatusEffect.FAINT); - expect(greninja!.isFainted()).toBe(true); + game.move.select(Moves.SPLASH); + await game.doKillOpponents(); + await game.phaseInterceptor.to("TurnEndPhase"); + game.doSelectModifier(); + await game.phaseInterceptor.to("QuietFormChangePhase"); - game.move.select(Moves.SPLASH); - await game.doKillOpponents(); - await game.phaseInterceptor.to(TurnEndPhase); - game.doSelectModifier(); - await game.phaseInterceptor.to(QuietFormChangePhase); + expect(greninja.formIndex).toBe(baseForm); + }); - expect(greninja!.formIndex).toBe(baseForm); - }, - ); + it("should not keep buffing Water Shuriken after Greninja switches to base form", async () => { + await game.classicMode.startBattle([ Species.GRENINJA ]); + + const waterShuriken = allMoves[Moves.WATER_SHURIKEN]; + vi.spyOn(waterShuriken, "calculateBattlePower"); + + let actualMultiHitType: MultiHitType | null = null; + const multiHitAttr = waterShuriken.getAttrs(MultiHitAttr)[0]; + vi.spyOn(multiHitAttr, "getHitCount").mockImplementation(() => { + actualMultiHitType = multiHitAttr.getMultiHitType(); + return 3; + }); + + // Wave 4: Use Water Shuriken in Ash form + let expectedBattlePower = 20; + let expectedMultiHitType = MultiHitType._3; + + game.move.select(Moves.WATER_SHURIKEN); + await game.phaseInterceptor.to("BerryPhase", false); + expect(waterShuriken.calculateBattlePower).toHaveLastReturnedWith(expectedBattlePower); + expect(actualMultiHitType).toBe(expectedMultiHitType); + + await game.doKillOpponents(); + await game.toNextWave(); + + // Wave 5: Use Water Shuriken in base form + expectedBattlePower = 15; + expectedMultiHitType = MultiHitType._2_TO_5; + + game.move.select(Moves.WATER_SHURIKEN); + await game.phaseInterceptor.to("BerryPhase", false); + expect(waterShuriken.calculateBattlePower).toHaveLastReturnedWith(expectedBattlePower); + expect(actualMultiHitType).toBe(expectedMultiHitType); + }); }); diff --git a/src/test/abilities/beast_boost.test.ts b/src/test/abilities/beast_boost.test.ts index 26bae7b8838..de31b979e32 100644 --- a/src/test/abilities/beast_boost.test.ts +++ b/src/test/abilities/beast_boost.test.ts @@ -34,7 +34,7 @@ describe("Abilities - Beast Boost", () => { }); it("should prefer highest stat to boost its corresponding stat stage by 1 when winning a battle", async() => { - await game.classicMode.startBattle([Species.SLOWBRO]); + await game.classicMode.startBattle([ Species.SLOWBRO ]); const playerPokemon = game.scene.getPlayerPokemon()!; // Set the pokemon's highest stat to DEF, so it should be picked by Beast Boost @@ -50,9 +50,9 @@ describe("Abilities - Beast Boost", () => { }, 20000); it("should use in-battle overriden stats when determining the stat stage to raise by 1", async() => { - game.override.enemyMoveset([Moves.GUARD_SPLIT]); + game.override.enemyMoveset([ Moves.GUARD_SPLIT ]); - await game.classicMode.startBattle([Species.SLOWBRO]); + await game.classicMode.startBattle([ Species.SLOWBRO ]); const playerPokemon = game.scene.getPlayerPokemon()!; // If the opponent uses Guard Split, the pokemon's second highest stat (SPATK) should be chosen @@ -70,7 +70,7 @@ describe("Abilities - Beast Boost", () => { it("should have order preference in case of stat ties", async() => { // Order preference follows the order of EFFECTIVE_STAT - await game.classicMode.startBattle([Species.SLOWBRO]); + await game.classicMode.startBattle([ Species.SLOWBRO ]); const playerPokemon = game.scene.getPlayerPokemon()!; diff --git a/src/test/abilities/competitive.test.ts b/src/test/abilities/competitive.test.ts new file mode 100644 index 00000000000..ecb276a1b8d --- /dev/null +++ b/src/test/abilities/competitive.test.ts @@ -0,0 +1,72 @@ +import { Stat } from "#enums/stat"; +import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Competitive", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + + game.override.battleType("single") + .enemySpecies(Species.BEEDRILL) + .enemyMoveset(Moves.TICKLE) + .startingLevel(1) + .moveset([ Moves.SPLASH, Moves.CLOSE_COMBAT ]) + .ability(Abilities.COMPETITIVE); + }); + + it("lower atk and def by 1 via tickle, then increase spatk by 4 via competitive", async () => { + await game.classicMode.startBattle([ Species.FLYGON ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(playerPokemon.getStatStage(Stat.ATK)).toBe(-1); + expect(playerPokemon.getStatStage(Stat.DEF)).toBe(-1); + expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(4); + }); + + it("lowering your own stats should not trigger competitive", async () => { + game.override.enemyMoveset(Moves.SPLASH); + await game.classicMode.startBattle([ Species.FLYGON ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + game.move.select(Moves.CLOSE_COMBAT); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(playerPokemon.getStatStage(Stat.SPDEF)).toBe(-1); + expect(playerPokemon.getStatStage(Stat.DEF)).toBe(-1); + expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(0); + }); + + it("white herb should remove only the negative effects", async () => { + game.override.startingHeldItems([{ name: "WHITE_HERB" }]); + await game.classicMode.startBattle([ Species.FLYGON ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(playerPokemon.getStatStage(Stat.ATK)).toBe(0); + expect(playerPokemon.getStatStage(Stat.DEF)).toBe(0); + expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(4); + }); +}); diff --git a/src/test/abilities/contrary.test.ts b/src/test/abilities/contrary.test.ts index 5221e821e70..c838a5a098e 100644 --- a/src/test/abilities/contrary.test.ts +++ b/src/test/abilities/contrary.test.ts @@ -44,8 +44,8 @@ describe("Abilities - Contrary", () => { it("should apply positive effects", async () => { game.override .enemyPassiveAbility(Abilities.CLEAR_BODY) - .moveset([Moves.TAIL_WHIP]); - await game.classicMode.startBattle([Species.SLOWBRO]); + .moveset([ Moves.TAIL_WHIP ]); + await game.classicMode.startBattle([ Species.SLOWBRO ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -60,9 +60,9 @@ describe("Abilities - Contrary", () => { it("should block negative effects", async () => { game.override .enemyPassiveAbility(Abilities.CLEAR_BODY) - .enemyMoveset([Moves.HOWL, Moves.HOWL, Moves.HOWL, Moves.HOWL]) - .moveset([Moves.SPLASH]); - await game.classicMode.startBattle([Species.SLOWBRO]); + .enemyMoveset([ Moves.HOWL, Moves.HOWL, Moves.HOWL, Moves.HOWL ]) + .moveset([ Moves.SPLASH ]); + await game.classicMode.startBattle([ Species.SLOWBRO ]); const enemyPokemon = game.scene.getEnemyPokemon()!; diff --git a/src/test/abilities/costar.test.ts b/src/test/abilities/costar.test.ts index 2fd1cb26408..3be29ea2dcf 100644 --- a/src/test/abilities/costar.test.ts +++ b/src/test/abilities/costar.test.ts @@ -9,7 +9,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - describe("Abilities - COSTAR", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -28,7 +27,7 @@ describe("Abilities - COSTAR", () => { game = new GameManager(phaserGame); game.override.battleType("double"); game.override.ability(Abilities.COSTAR); - game.override.moveset([Moves.SPLASH, Moves.NASTY_PLOT]); + game.override.moveset([ Moves.SPLASH, Moves.NASTY_PLOT ]); game.override.enemyMoveset(Moves.SPLASH); }); @@ -38,9 +37,9 @@ describe("Abilities - COSTAR", () => { async () => { game.override.enemyAbility(Abilities.BALL_FETCH); - await game.startBattle([Species.MAGIKARP, Species.MAGIKARP, Species.FLAMIGO]); + await game.startBattle([ Species.MAGIKARP, Species.MAGIKARP, Species.FLAMIGO ]); - let [leftPokemon, rightPokemon] = game.scene.getPlayerField(); + let [ leftPokemon, rightPokemon ] = game.scene.getPlayerField(); game.move.select(Moves.NASTY_PLOT); await game.phaseInterceptor.to(CommandPhase); @@ -55,7 +54,7 @@ describe("Abilities - COSTAR", () => { game.doSwitchPokemon(2); await game.phaseInterceptor.to(MessagePhase); - [leftPokemon, rightPokemon] = game.scene.getPlayerField(); + [ leftPokemon, rightPokemon ] = game.scene.getPlayerField(); expect(leftPokemon.getStatStage(Stat.SPATK)).toBe(2); expect(rightPokemon.getStatStage(Stat.SPATK)).toBe(2); }, @@ -66,9 +65,9 @@ describe("Abilities - COSTAR", () => { async () => { game.override.enemyAbility(Abilities.INTIMIDATE); - await game.startBattle([Species.MAGIKARP, Species.MAGIKARP, Species.FLAMIGO]); + await game.startBattle([ Species.MAGIKARP, Species.MAGIKARP, Species.FLAMIGO ]); - let [leftPokemon, rightPokemon] = game.scene.getPlayerField(); + let [ leftPokemon, rightPokemon ] = game.scene.getPlayerField(); expect(leftPokemon.getStatStage(Stat.ATK)).toBe(-2); expect(leftPokemon.getStatStage(Stat.ATK)).toBe(-2); @@ -78,7 +77,7 @@ describe("Abilities - COSTAR", () => { game.doSwitchPokemon(2); await game.phaseInterceptor.to(MessagePhase); - [leftPokemon, rightPokemon] = game.scene.getPlayerField(); + [ leftPokemon, rightPokemon ] = game.scene.getPlayerField(); expect(leftPokemon.getStatStage(Stat.ATK)).toBe(-2); expect(rightPokemon.getStatStage(Stat.ATK)).toBe(-2); }, diff --git a/src/test/abilities/dancer.test.ts b/src/test/abilities/dancer.test.ts index 7564a254dbe..8fa3d444f37 100644 --- a/src/test/abilities/dancer.test.ts +++ b/src/test/abilities/dancer.test.ts @@ -8,7 +8,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Abilities - Dancer", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -27,22 +26,22 @@ describe("Abilities - Dancer", () => { game = new GameManager(phaserGame); game.override .battleType("double") - .moveset([Moves.SWORDS_DANCE, Moves.SPLASH]) + .moveset([ Moves.SWORDS_DANCE, Moves.SPLASH ]) .enemySpecies(Species.MAGIKARP) .enemyAbility(Abilities.DANCER) - .enemyMoveset([Moves.VICTORY_DANCE]); + .enemyMoveset([ Moves.VICTORY_DANCE ]); }); // Reference Link: https://bulbapedia.bulbagarden.net/wiki/Dancer_(Ability) it("triggers when dance moves are used, doesn't consume extra PP", async () => { - await game.classicMode.startBattle([Species.ORICORIO, Species.FEEBAS]); + await game.classicMode.startBattle([ Species.ORICORIO, Species.FEEBAS ]); - const [oricorio] = game.scene.getPlayerField(); + const [ oricorio ] = game.scene.getPlayerField(); game.move.select(Moves.SPLASH); game.move.select(Moves.SWORDS_DANCE, 1); - await game.setTurnOrder([BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("MovePhase"); // immediately copies ally move await game.phaseInterceptor.to("MovePhase", false); diff --git a/src/test/abilities/defiant.test.ts b/src/test/abilities/defiant.test.ts new file mode 100644 index 00000000000..aa8d250dad7 --- /dev/null +++ b/src/test/abilities/defiant.test.ts @@ -0,0 +1,70 @@ +import { Stat } from "#enums/stat"; +import { TurnInitPhase } from "#app/phases/turn-init-phase"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Defiant", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + + game.override.battleType("single") + .enemySpecies(Species.BEEDRILL) + .enemyMoveset(Moves.TICKLE) + .startingLevel(1) + .moveset([ Moves.SPLASH, Moves.CLOSE_COMBAT ]) + .ability(Abilities.DEFIANT); + }); + + it("lower atk and def by 1 via tickle, then increase atk by 4 via defiant", async () => { + await game.classicMode.startBattle([ Species.FLYGON ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(playerPokemon.getStatStage(Stat.ATK)).toBe(3); + expect(playerPokemon.getStatStage(Stat.DEF)).toBe(-1); + }); + + it("lowering your own stats should not trigger defiant", async () => { + game.override.enemyMoveset(Moves.SPLASH); + await game.classicMode.startBattle([ Species.FLYGON ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + game.move.select(Moves.CLOSE_COMBAT); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(playerPokemon.getStatStage(Stat.SPDEF)).toBe(-1); + expect(playerPokemon.getStatStage(Stat.DEF)).toBe(-1); + expect(playerPokemon.getStatStage(Stat.ATK)).toBe(0); + }); + + it("white herb should remove only the negative effects", async () => { + game.override.startingHeldItems([{ name: "WHITE_HERB" }]); + await game.classicMode.startBattle([ Species.FLYGON ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to(TurnInitPhase); + + expect(playerPokemon.getStatStage(Stat.DEF)).toBe(0); + expect(playerPokemon.getStatStage(Stat.ATK)).toBe(3); + }); +}); diff --git a/src/test/abilities/disguise.test.ts b/src/test/abilities/disguise.test.ts index 0268a738c0e..0241aa4b9ea 100644 --- a/src/test/abilities/disguise.test.ts +++ b/src/test/abilities/disguise.test.ts @@ -1,14 +1,14 @@ +import { BattlerIndex } from "#app/battle"; +import { StatusEffect } from "#app/data/status-effect"; import { toDmgValue } from "#app/utils"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; -import { StatusEffect } from "#app/data/status-effect"; import { Stat } from "#enums/stat"; import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Abilities - Disguise", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -32,7 +32,7 @@ describe("Abilities - Disguise", () => { .enemySpecies(Species.MIMIKYU) .enemyMoveset(Moves.SPLASH) .starterSpecies(Species.REGIELEKI) - .moveset([Moves.SHADOW_SNEAK, Moves.VACUUM_WAVE, Moves.TOXIC_THREAD, Moves.SPLASH]); + .moveset([ Moves.SHADOW_SNEAK, Moves.VACUUM_WAVE, Moves.TOXIC_THREAD, Moves.SPLASH ]); }); it("takes no damage from attacking move and transforms to Busted form, takes 1/8 max HP damage from the disguise breaking", async () => { @@ -107,7 +107,7 @@ describe("Abilities - Disguise", () => { }); it("persists form change when switched out", async () => { - game.override.enemyMoveset([Moves.SHADOW_SNEAK]); + game.override.enemyMoveset([ Moves.SHADOW_SNEAK ]); game.override.starterSpecies(0); await game.classicMode.startBattle([ Species.MIMIKYU, Species.FURRET ]); @@ -193,7 +193,7 @@ describe("Abilities - Disguise", () => { }); it("doesn't faint twice when fainting due to Disguise break damage, nor prevent faint from Disguise break damage if using Endure", async () => { - game.override.enemyMoveset([Moves.ENDURE]); + game.override.enemyMoveset([ Moves.ENDURE ]); await game.classicMode.startBattle(); const mimikyu = game.scene.getEnemyPokemon()!; @@ -208,7 +208,7 @@ describe("Abilities - Disguise", () => { it("activates when Aerilate circumvents immunity to the move's base type", async () => { game.override.ability(Abilities.AERILATE); - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); await game.classicMode.startBattle(); @@ -223,4 +223,17 @@ describe("Abilities - Disguise", () => { expect(mimikyu.formIndex).toBe(bustedForm); expect(mimikyu.hp).toBe(maxHp - disguiseDamage); }); + + it("doesn't trigger if user is behind a substitute", async () => { + game.override + .enemyMoveset(Moves.SUBSTITUTE) + .moveset(Moves.POWER_TRIP); + await game.classicMode.startBattle(); + + game.move.select(Moves.POWER_TRIP); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.toNextTurn(); + + expect(game.scene.getEnemyPokemon()!.formIndex).toBe(disguisedForm); + }); }); diff --git a/src/test/abilities/dry_skin.test.ts b/src/test/abilities/dry_skin.test.ts index a97914660bc..314564df15c 100644 --- a/src/test/abilities/dry_skin.test.ts +++ b/src/test/abilities/dry_skin.test.ts @@ -28,7 +28,7 @@ describe("Abilities - Dry Skin", () => { .enemyMoveset(Moves.SPLASH) .enemySpecies(Species.CHARMANDER) .ability(Abilities.BALL_FETCH) - .moveset([Moves.SUNNY_DAY, Moves.RAIN_DANCE, Moves.SPLASH, Moves.WATER_GUN]) + .moveset([ Moves.SUNNY_DAY, Moves.RAIN_DANCE, Moves.SPLASH, Moves.WATER_GUN ]) .starterSpecies(Species.CHANDELURE); }); @@ -69,7 +69,7 @@ describe("Abilities - Dry Skin", () => { }); it("opposing fire attacks do 25% more damage", async () => { - game.override.moveset([Moves.FLAMETHROWER]); + game.override.moveset([ Moves.FLAMETHROWER ]); await game.classicMode.startBattle(); const enemy = game.scene.getEnemyPokemon()!; @@ -105,7 +105,7 @@ describe("Abilities - Dry Skin", () => { }); it("opposing water attacks do not heal if they were protected from", async () => { - game.override.enemyMoveset([Moves.PROTECT]); + game.override.enemyMoveset([ Moves.PROTECT ]); await game.classicMode.startBattle(); @@ -119,7 +119,7 @@ describe("Abilities - Dry Skin", () => { }); it("multi-strike water attacks only heal once", async () => { - game.override.moveset([Moves.WATER_GUN, Moves.WATER_SHURIKEN]); + game.override.moveset([ Moves.WATER_GUN, Moves.WATER_SHURIKEN ]); await game.classicMode.startBattle(); diff --git a/src/test/abilities/flash_fire.test.ts b/src/test/abilities/flash_fire.test.ts index 9c78de99575..f03e1689649 100644 --- a/src/test/abilities/flash_fire.test.ts +++ b/src/test/abilities/flash_fire.test.ts @@ -37,8 +37,8 @@ describe("Abilities - Flash Fire", () => { it("immune to Fire-type moves", async () => { - game.override.enemyMoveset([Moves.EMBER]).moveset(Moves.SPLASH); - await game.classicMode.startBattle([Species.BLISSEY]); + game.override.enemyMoveset([ Moves.EMBER ]).moveset(Moves.SPLASH); + await game.classicMode.startBattle([ Species.BLISSEY ]); const blissey = game.scene.getPlayerPokemon()!; @@ -48,8 +48,8 @@ describe("Abilities - Flash Fire", () => { }, 20000); it("not activate if the Pokémon is protected from the Fire-type move", async () => { - game.override.enemyMoveset([Moves.EMBER]).moveset([Moves.PROTECT]); - await game.classicMode.startBattle([Species.BLISSEY]); + game.override.enemyMoveset([ Moves.EMBER ]).moveset([ Moves.PROTECT ]); + await game.classicMode.startBattle([ Species.BLISSEY ]); const blissey = game.scene.getPlayerPokemon()!; @@ -59,8 +59,8 @@ describe("Abilities - Flash Fire", () => { }, 20000); it("activated by Will-O-Wisp", async () => { - game.override.enemyMoveset([Moves.WILL_O_WISP]).moveset(Moves.SPLASH); - await game.classicMode.startBattle([Species.BLISSEY]); + game.override.enemyMoveset([ Moves.WILL_O_WISP ]).moveset(Moves.SPLASH); + await game.classicMode.startBattle([ Species.BLISSEY ]); const blissey = game.scene.getPlayerPokemon()!; @@ -74,9 +74,9 @@ describe("Abilities - Flash Fire", () => { }, 20000); it("activated after being frozen", async () => { - game.override.enemyMoveset([Moves.EMBER]).moveset(Moves.SPLASH); + game.override.enemyMoveset([ Moves.EMBER ]).moveset(Moves.SPLASH); game.override.statusEffect(StatusEffect.FREEZE); - await game.classicMode.startBattle([Species.BLISSEY]); + await game.classicMode.startBattle([ Species.BLISSEY ]); const blissey = game.scene.getPlayerPokemon()!; @@ -87,12 +87,12 @@ describe("Abilities - Flash Fire", () => { }, 20000); it("not passing with baton pass", async () => { - game.override.enemyMoveset([Moves.EMBER]).moveset([Moves.BATON_PASS]); - await game.classicMode.startBattle([Species.BLISSEY, Species.CHANSEY]); + game.override.enemyMoveset([ Moves.EMBER ]).moveset([ Moves.BATON_PASS ]); + await game.classicMode.startBattle([ Species.BLISSEY, Species.CHANSEY ]); // ensure use baton pass after enemy moved game.move.select(Moves.BATON_PASS); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); game.doSelectPartyPokemon(1); @@ -103,16 +103,16 @@ describe("Abilities - Flash Fire", () => { }, 20000); it("boosts Fire-type move when the ability is activated", async () => { - game.override.enemyMoveset([Moves.FIRE_PLEDGE]).moveset([Moves.EMBER, Moves.SPLASH]); + game.override.enemyMoveset([ Moves.FIRE_PLEDGE ]).moveset([ Moves.EMBER, Moves.SPLASH ]); game.override.enemyAbility(Abilities.FLASH_FIRE).ability(Abilities.NONE); - await game.classicMode.startBattle([Species.BLISSEY]); + await game.classicMode.startBattle([ Species.BLISSEY ]); const blissey = game.scene.getPlayerPokemon()!; const initialHP = 1000; blissey.hp = initialHP; // first turn game.move.select(Moves.EMBER); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to(TurnEndPhase); const originalDmg = initialHP - blissey.hp; @@ -131,7 +131,7 @@ describe("Abilities - Flash Fire", () => { game.override.moveset(Moves.FIRE_PLEDGE).enemyMoveset(Moves.EMBER); game.override.enemyAbility(Abilities.NONE).ability(Abilities.FLASH_FIRE); game.override.enemySpecies(Species.BLISSEY); - await game.classicMode.startBattle([Species.RATTATA]); + await game.classicMode.startBattle([ Species.RATTATA ]); const blissey = game.scene.getEnemyPokemon()!; const initialHP = 1000; @@ -139,7 +139,7 @@ describe("Abilities - Flash Fire", () => { // first turn game.move.select(Moves.FIRE_PLEDGE); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); await game.move.forceMiss(); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/abilities/flower_gift.test.ts b/src/test/abilities/flower_gift.test.ts index 256b61c6fea..04ada598f22 100644 --- a/src/test/abilities/flower_gift.test.ts +++ b/src/test/abilities/flower_gift.test.ts @@ -21,7 +21,7 @@ describe("Abilities - Flower Gift", () => { */ const testRevertFormAgainstAbility = async (game: GameManager, ability: Abilities) => { game.override.starterForms({ [Species.CASTFORM]: SUNSHINE_FORM }).enemyAbility(ability); - await game.classicMode.startBattle([Species.CASTFORM]); + await game.classicMode.startBattle([ Species.CASTFORM ]); game.move.select(Moves.SPLASH); @@ -41,7 +41,7 @@ describe("Abilities - Flower Gift", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.SPLASH, Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.SKILL_SWAP]) + .moveset([ Moves.SPLASH, Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.SKILL_SWAP ]) .enemySpecies(Species.MAGIKARP) .enemyMoveset(Moves.SPLASH) .enemyAbility(Abilities.BALL_FETCH); @@ -50,7 +50,7 @@ describe("Abilities - Flower Gift", () => { // TODO: Uncomment expect statements when the ability is implemented - currently does not increase stats of allies it("increases the ATK and SPDEF stat stages of the Pokémon with this Ability and its allies by 1.5× during Harsh Sunlight", async () => { game.override.battleType("double"); - await game.classicMode.startBattle([Species.CHERRIM, Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.CHERRIM, Species.MAGIKARP ]); const [ cherrim ] = game.scene.getPlayerField(); const cherrimAtkStat = cherrim.getEffectiveStat(Stat.ATK); @@ -62,7 +62,7 @@ describe("Abilities - Flower Gift", () => { game.move.select(Moves.SUNNY_DAY, 0); game.move.select(Moves.SPLASH, 1); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("TurnEndPhase"); expect(cherrim.formIndex).toBe(SUNSHINE_FORM); @@ -74,7 +74,7 @@ describe("Abilities - Flower Gift", () => { it("changes the Pokemon's form during Harsh Sunlight", async () => { game.override.weather(WeatherType.HARSH_SUN); - await game.classicMode.startBattle([Species.CHERRIM]); + await game.classicMode.startBattle([ Species.CHERRIM ]); const cherrim = game.scene.getPlayerPokemon()!; expect(cherrim.formIndex).toBe(SUNSHINE_FORM); @@ -91,9 +91,9 @@ describe("Abilities - Flower Gift", () => { }); it("reverts to Overcast Form when the Pokémon loses Flower Gift, changes form under Harsh Sunlight/Sunny when it regains it", async () => { - game.override.enemyMoveset([Moves.SKILL_SWAP]).weather(WeatherType.HARSH_SUN); + game.override.enemyMoveset([ Moves.SKILL_SWAP ]).weather(WeatherType.HARSH_SUN); - await game.classicMode.startBattle([Species.CHERRIM]); + await game.classicMode.startBattle([ Species.CHERRIM ]); const cherrim = game.scene.getPlayerPokemon()!; @@ -110,16 +110,16 @@ describe("Abilities - Flower Gift", () => { }); it("reverts to Overcast Form when the Flower Gift is suppressed, changes form under Harsh Sunlight/Sunny when it regains it", async () => { - game.override.enemyMoveset([Moves.GASTRO_ACID]).weather(WeatherType.HARSH_SUN); + game.override.enemyMoveset([ Moves.GASTRO_ACID ]).weather(WeatherType.HARSH_SUN); - await game.classicMode.startBattle([Species.CHERRIM, Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.CHERRIM, Species.MAGIKARP ]); const cherrim = game.scene.getPlayerPokemon()!; expect(cherrim.formIndex).toBe(SUNSHINE_FORM); game.move.select(Moves.SPLASH); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase"); expect(cherrim.summonData.abilitySuppressed).toBe(true); @@ -140,7 +140,7 @@ describe("Abilities - Flower Gift", () => { it("should be in Overcast Form after the user is switched out", async () => { game.override.weather(WeatherType.SUNNY); - await game.classicMode.startBattle([Species.CASTFORM, Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.CASTFORM, Species.MAGIKARP ]); const cherrim = game.scene.getPlayerPokemon()!; expect(cherrim.formIndex).toBe(SUNSHINE_FORM); diff --git a/src/test/abilities/forecast.test.ts b/src/test/abilities/forecast.test.ts index c1eb3600b8b..6da31307789 100644 --- a/src/test/abilities/forecast.test.ts +++ b/src/test/abilities/forecast.test.ts @@ -30,7 +30,7 @@ describe("Abilities - Forecast", () => { */ const testWeatherFormChange = async (game: GameManager, weather: WeatherType, form: number, initialForm?: number) => { game.override.weather(weather).starterForms({ [Species.CASTFORM]: initialForm }); - await game.startBattle([Species.CASTFORM]); + await game.startBattle([ Species.CASTFORM ]); game.move.select(Moves.SPLASH); @@ -44,7 +44,7 @@ describe("Abilities - Forecast", () => { */ const testRevertFormAgainstAbility = async (game: GameManager, ability: Abilities) => { game.override.starterForms({ [Species.CASTFORM]: SUNNY_FORM }).enemyAbility(ability); - await game.startBattle([Species.CASTFORM]); + await game.startBattle([ Species.CASTFORM ]); game.move.select(Moves.SPLASH); @@ -64,7 +64,7 @@ describe("Abilities - Forecast", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.SPLASH, Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.TACKLE]) + .moveset([ Moves.SPLASH, Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.TACKLE ]) .enemySpecies(Species.MAGIKARP) .enemyMoveset(Moves.SPLASH) .enemyAbility(Abilities.BALL_FETCH); @@ -72,14 +72,14 @@ describe("Abilities - Forecast", () => { it("changes form based on weather", async () => { game.override - .moveset([Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.SNOWSCAPE, Moves.SPLASH]) + .moveset([ Moves.RAIN_DANCE, Moves.SUNNY_DAY, Moves.SNOWSCAPE, Moves.SPLASH ]) .battleType("double") .starterForms({ [Species.KYOGRE]: 1, [Species.GROUDON]: 1, [Species.RAYQUAZA]: 1 }); - await game.startBattle([Species.CASTFORM, Species.FEEBAS, Species.KYOGRE, Species.GROUDON, Species.RAYQUAZA, Species.ALTARIA]); + await game.startBattle([ Species.CASTFORM, Species.FEEBAS, Species.KYOGRE, Species.GROUDON, Species.RAYQUAZA, Species.ALTARIA ]); vi.spyOn(game.scene.getParty()[5], "getAbility").mockReturnValue(allAbilities[Abilities.CLOUD_NINE]); @@ -107,7 +107,7 @@ describe("Abilities - Forecast", () => { expect(castform.formIndex).toBe(SNOWY_FORM); - game.override.moveset([Moves.HAIL, Moves.SANDSTORM, Moves.SNOWSCAPE, Moves.SPLASH]); + game.override.moveset([ Moves.HAIL, Moves.SANDSTORM, Moves.SNOWSCAPE, Moves.SPLASH ]); game.move.select(Moves.SANDSTORM); game.move.select(Moves.SPLASH, 1); @@ -190,7 +190,7 @@ describe("Abilities - Forecast", () => { it("has no effect on Pokémon other than Castform", async () => { game.override.enemyAbility(Abilities.FORECAST).enemySpecies(Species.SHUCKLE); - await game.startBattle([Species.CASTFORM]); + await game.startBattle([ Species.CASTFORM ]); game.move.select(Moves.RAIN_DANCE); await game.phaseInterceptor.to(TurnEndPhase); @@ -200,8 +200,8 @@ describe("Abilities - Forecast", () => { }); it("reverts to Normal Form when Castform loses Forecast, changes form to match the weather when it regains it", async () => { - game.override.moveset([Moves.SKILL_SWAP, Moves.WORRY_SEED, Moves.SPLASH]).weather(WeatherType.RAIN).battleType("double"); - await game.startBattle([Species.CASTFORM, Species.FEEBAS]); + game.override.moveset([ Moves.SKILL_SWAP, Moves.WORRY_SEED, Moves.SPLASH ]).weather(WeatherType.RAIN).battleType("double"); + await game.startBattle([ Species.CASTFORM, Species.FEEBAS ]); const castform = game.scene.getPlayerField()[0]; @@ -209,7 +209,7 @@ describe("Abilities - Forecast", () => { game.move.select(Moves.SKILL_SWAP, 0, BattlerIndex.PLAYER_2); game.move.select(Moves.SKILL_SWAP, 1, BattlerIndex.PLAYER); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(castform.formIndex).toBe(NORMAL_FORM); @@ -221,22 +221,22 @@ describe("Abilities - Forecast", () => { game.move.select(Moves.SPLASH); game.move.select(Moves.WORRY_SEED, 1, BattlerIndex.PLAYER); - await game.setTurnOrder([BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(castform.formIndex).toBe(NORMAL_FORM); }); it("reverts to Normal Form when Forecast is suppressed, changes form to match the weather when it regains it", async () => { - game.override.enemyMoveset([Moves.GASTRO_ACID]).weather(WeatherType.RAIN); - await game.startBattle([Species.CASTFORM, Species.PIKACHU]); + game.override.enemyMoveset([ Moves.GASTRO_ACID ]).weather(WeatherType.RAIN); + await game.startBattle([ Species.CASTFORM, Species.PIKACHU ]); const castform = game.scene.getPlayerPokemon()!; expect(castform.formIndex).toBe(RAINY_FORM); // First turn - Forecast is suppressed game.move.select(Moves.SPLASH); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.move.forceHit(); await game.phaseInterceptor.to(TurnEndPhase); @@ -259,8 +259,8 @@ describe("Abilities - Forecast", () => { }); it("does not change Castform's form until after Stealth Rock deals damage", async () => { - game.override.weather(WeatherType.RAIN).enemyMoveset([Moves.STEALTH_ROCK]); - await game.startBattle([Species.PIKACHU, Species.CASTFORM]); + game.override.weather(WeatherType.RAIN).enemyMoveset([ Moves.STEALTH_ROCK ]); + await game.startBattle([ Species.PIKACHU, Species.CASTFORM ]); // First turn - set up stealth rock game.move.select(Moves.SPLASH); @@ -284,7 +284,7 @@ describe("Abilities - Forecast", () => { it("should be in Normal Form after the user is switched out", async () => { game.override.weather(WeatherType.RAIN); - await game.startBattle([Species.CASTFORM, Species.MAGIKARP]); + await game.startBattle([ Species.CASTFORM, Species.MAGIKARP ]); const castform = game.scene.getPlayerPokemon()!; expect(castform.formIndex).toBe(RAINY_FORM); diff --git a/src/test/abilities/galvanize.test.ts b/src/test/abilities/galvanize.test.ts index 1b7dde9ba60..438f166174d 100644 --- a/src/test/abilities/galvanize.test.ts +++ b/src/test/abilities/galvanize.test.ts @@ -10,7 +10,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; - describe("Abilities - Galvanize", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -32,7 +31,7 @@ describe("Abilities - Galvanize", () => { .battleType("single") .startingLevel(100) .ability(Abilities.GALVANIZE) - .moveset([Moves.TACKLE, Moves.REVELATION_DANCE, Moves.FURY_SWIPES]) + .moveset([ Moves.TACKLE, Moves.REVELATION_DANCE, Moves.FURY_SWIPES ]) .enemySpecies(Species.DUSCLOPS) .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH) @@ -86,7 +85,7 @@ describe("Abilities - Galvanize", () => { it("should not change the type of variable-type moves", async () => { game.override.enemySpecies(Species.MIGHTYENA); - await game.startBattle([Species.ESPEON]); + await game.startBattle([ Species.ESPEON ]); const playerPokemon = game.scene.getPlayerPokemon()!; vi.spyOn(playerPokemon, "getMoveType"); @@ -112,7 +111,7 @@ describe("Abilities - Galvanize", () => { vi.spyOn(enemyPokemon, "apply"); game.move.select(Moves.FURY_SWIPES); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.move.forceHit(); await game.phaseInterceptor.to("MoveEffectPhase"); diff --git a/src/test/abilities/gorilla_tactics.test.ts b/src/test/abilities/gorilla_tactics.test.ts index 5e92950526e..8aee365eb8f 100644 --- a/src/test/abilities/gorilla_tactics.test.ts +++ b/src/test/abilities/gorilla_tactics.test.ts @@ -25,15 +25,15 @@ describe("Abilities - Gorilla Tactics", () => { game.override .battleType("single") .enemyAbility(Abilities.BALL_FETCH) - .enemyMoveset([Moves.SPLASH, Moves.DISABLE]) + .enemyMoveset([ Moves.SPLASH, Moves.DISABLE ]) .enemySpecies(Species.MAGIKARP) .enemyLevel(30) - .moveset([Moves.SPLASH, Moves.TACKLE, Moves.GROWL]) + .moveset([ Moves.SPLASH, Moves.TACKLE, Moves.GROWL ]) .ability(Abilities.GORILLA_TACTICS); }); it("boosts the Pokémon's Attack by 50%, but limits the Pokémon to using only one move", async () => { - await game.classicMode.startBattle([Species.GALAR_DARMANITAN]); + await game.classicMode.startBattle([ Species.GALAR_DARMANITAN ]); const darmanitan = game.scene.getPlayerPokemon()!; const initialAtkStat = darmanitan.getStat(Stat.ATK); @@ -50,7 +50,7 @@ describe("Abilities - Gorilla Tactics", () => { }); it("should struggle if the only usable move is disabled", async () => { - await game.classicMode.startBattle([Species.GALAR_DARMANITAN]); + await game.classicMode.startBattle([ Species.GALAR_DARMANITAN ]); const darmanitan = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; @@ -64,7 +64,7 @@ describe("Abilities - Gorilla Tactics", () => { game.move.select(Moves.GROWL); await game.forceEnemyMove(Moves.DISABLE); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase"); expect(enemy.getStatStage(Stat.ATK)).toBe(-1); // Only the effect of the first Growl should be applied @@ -73,7 +73,7 @@ describe("Abilities - Gorilla Tactics", () => { await game.toNextTurn(); game.move.select(Moves.TACKLE); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(darmanitan.hp).toBeLessThan(darmanitan.getMaxHp()); diff --git a/src/test/abilities/gulp_missile.test.ts b/src/test/abilities/gulp_missile.test.ts index d981f009974..01b68d0c89d 100644 --- a/src/test/abilities/gulp_missile.test.ts +++ b/src/test/abilities/gulp_missile.test.ts @@ -1,13 +1,14 @@ -import { BattlerTagType } from "#enums/battler-tag-type"; -import { StatusEffect } from "#enums/status-effect"; +import { BattlerIndex } from "#app/battle"; import Pokemon from "#app/field/pokemon"; -import GameManager from "#test/utils/gameManager"; import { Abilities } from "#enums/abilities"; +import { BattlerTagType } from "#enums/battler-tag-type"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; +import { Stat } from "#enums/stat"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { Stat } from "#enums/stat"; describe("Abilities - Gulp Missile", () => { let phaserGame: Phaser.Game; @@ -40,8 +41,9 @@ describe("Abilities - Gulp Missile", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override + .disableCrits() .battleType("single") - .moveset([Moves.SURF, Moves.DIVE, Moves.SPLASH]) + .moveset([ Moves.SURF, Moves.DIVE, Moves.SPLASH, Moves.SUBSTITUTE ]) .enemySpecies(Species.SNORLAX) .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH) @@ -49,7 +51,7 @@ describe("Abilities - Gulp Missile", () => { }); it("changes to Gulping Form if HP is over half when Surf or Dive is used", async () => { - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; game.move.select(Moves.DIVE); @@ -63,7 +65,7 @@ describe("Abilities - Gulp Missile", () => { }); it("changes to Gorging Form if HP is under half when Surf or Dive is used", async () => { - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.49); @@ -77,7 +79,7 @@ describe("Abilities - Gulp Missile", () => { }); it("changes to base form when switched out after Surf or Dive is used", async () => { - await game.classicMode.startBattle([Species.CRAMORANT, Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.CRAMORANT, Species.MAGIKARP ]); const cramorant = game.scene.getPlayerPokemon()!; game.move.select(Moves.SURF); @@ -92,7 +94,7 @@ describe("Abilities - Gulp Missile", () => { }); it("changes form during Dive's charge turn", async () => { - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; game.move.select(Moves.DIVE); @@ -104,7 +106,7 @@ describe("Abilities - Gulp Missile", () => { it("deals 1/4 of the attacker's maximum HP when hit by a damaging attack", async () => { game.override.enemyMoveset(Moves.TACKLE); - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const enemy = game.scene.getEnemyPokemon()!; vi.spyOn(enemy, "damageAndUpdate"); @@ -117,7 +119,7 @@ describe("Abilities - Gulp Missile", () => { it("does not have any effect when hit by non-damaging attack", async () => { game.override.enemyMoveset(Moves.TAIL_WHIP); - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.55); @@ -136,7 +138,7 @@ describe("Abilities - Gulp Missile", () => { it("lowers attacker's DEF stat stage by 1 when hit in Gulping form", async () => { game.override.enemyMoveset(Moves.TACKLE); - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; @@ -160,7 +162,7 @@ describe("Abilities - Gulp Missile", () => { it("paralyzes the enemy when hit in Gorging form", async () => { game.override.enemyMoveset(Moves.TACKLE); - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; @@ -184,7 +186,7 @@ describe("Abilities - Gulp Missile", () => { it("does not activate the ability when underwater", async () => { game.override.enemyMoveset(Moves.SURF); - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; @@ -197,7 +199,7 @@ describe("Abilities - Gulp Missile", () => { it("prevents effect damage but inflicts secondary effect on attacker with Magic Guard", async () => { game.override.enemyMoveset(Moves.TACKLE).enemyAbility(Abilities.MAGIC_GUARD); - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; @@ -221,7 +223,7 @@ describe("Abilities - Gulp Missile", () => { it("activates on faint", async () => { game.override.enemyMoveset(Moves.THUNDERBOLT); - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; @@ -234,10 +236,29 @@ describe("Abilities - Gulp Missile", () => { expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.DEF)).toBe(-1); }); + it("doesn't trigger if user is behind a substitute", async () => { + game.override + .enemyAbility(Abilities.STURDY) + .enemyMoveset([ Moves.SPLASH, Moves.POWER_TRIP ]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); + + game.move.select(Moves.SURF); + await game.forceEnemyMove(Moves.SPLASH); + await game.toNextTurn(); + + expect(game.scene.getPlayerPokemon()!.formIndex).toBe(GULPING_FORM); + + game.move.select(Moves.SUBSTITUTE); + await game.forceEnemyMove(Moves.POWER_TRIP); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + await game.toNextTurn(); + + expect(game.scene.getPlayerPokemon()!.formIndex).toBe(GULPING_FORM); + }); it("cannot be suppressed", async () => { game.override.enemyMoveset(Moves.GASTRO_ACID); - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.55); @@ -257,7 +278,7 @@ describe("Abilities - Gulp Missile", () => { it("cannot be swapped with another ability", async () => { game.override.enemyMoveset(Moves.SKILL_SWAP); - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); const cramorant = game.scene.getPlayerPokemon()!; vi.spyOn(cramorant, "getHpRatio").mockReturnValue(.55); @@ -278,7 +299,7 @@ describe("Abilities - Gulp Missile", () => { it("cannot be copied", async () => { game.override.enemyAbility(Abilities.TRACE); - await game.classicMode.startBattle([Species.CRAMORANT]); + await game.classicMode.startBattle([ Species.CRAMORANT ]); game.move.select(Moves.SPLASH); await game.phaseInterceptor.to("TurnStartPhase"); diff --git a/src/test/abilities/heatproof.test.ts b/src/test/abilities/heatproof.test.ts index 61c406201bd..bf4e99ce467 100644 --- a/src/test/abilities/heatproof.test.ts +++ b/src/test/abilities/heatproof.test.ts @@ -33,7 +33,7 @@ describe("Abilities - Heatproof", () => { .enemyLevel(100) .starterSpecies(Species.CHANDELURE) .ability(Abilities.BALL_FETCH) - .moveset([Moves.FLAMETHROWER, Moves.SPLASH]) + .moveset([ Moves.FLAMETHROWER, Moves.SPLASH ]) .startingLevel(100); }); diff --git a/src/test/abilities/hustle.test.ts b/src/test/abilities/hustle.test.ts index 29cbfdc1a5d..c4c4818040d 100644 --- a/src/test/abilities/hustle.test.ts +++ b/src/test/abilities/hustle.test.ts @@ -34,7 +34,7 @@ describe("Abilities - Hustle", () => { }); it("increases the user's Attack stat by 50%", async () => { - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const pikachu = game.scene.getPlayerPokemon()!; const atk = pikachu.stats[Stat.ATK]; @@ -48,7 +48,7 @@ describe("Abilities - Hustle", () => { }); it("lowers the accuracy of the user's physical moves by 20%", async () => { - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const pikachu = game.scene.getPlayerPokemon()!; vi.spyOn(pikachu, "getAccuracyMultiplier"); @@ -60,7 +60,7 @@ describe("Abilities - Hustle", () => { }); it("does not affect non-physical moves", async () => { - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const pikachu = game.scene.getPlayerPokemon()!; const spatk = pikachu.stats[Stat.SPATK]; @@ -78,7 +78,7 @@ describe("Abilities - Hustle", () => { game.override.startingLevel(100); game.override.enemyLevel(30); - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const pikachu = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; diff --git a/src/test/abilities/hyper_cutter.test.ts b/src/test/abilities/hyper_cutter.test.ts index ec947add939..e51fef6bd49 100644 --- a/src/test/abilities/hyper_cutter.test.ts +++ b/src/test/abilities/hyper_cutter.test.ts @@ -24,7 +24,7 @@ describe("Abilities - Hyper Cutter", () => { game = new GameManager(phaserGame); game.override .battleType("single") - .moveset([Moves.SAND_ATTACK, Moves.NOBLE_ROAR, Moves.DEFOG, Moves.OCTOLOCK]) + .moveset([ Moves.SAND_ATTACK, Moves.NOBLE_ROAR, Moves.DEFOG, Moves.OCTOLOCK ]) .ability(Abilities.BALL_FETCH) .enemySpecies(Species.SHUCKLE) .enemyAbility(Abilities.HYPER_CUTTER) @@ -46,11 +46,11 @@ describe("Abilities - Hyper Cutter", () => { await game.toNextTurn(); game.move.select(Moves.SAND_ATTACK); await game.toNextTurn(); - game.override.moveset([Moves.STRING_SHOT]); + game.override.moveset([ Moves.STRING_SHOT ]); game.move.select(Moves.STRING_SHOT); await game.toNextTurn(); expect(enemy.getStatStage(Stat.ATK)).toEqual(0); - [Stat.ACC, Stat.DEF, Stat.EVA, Stat.SPATK, Stat.SPDEF, Stat.SPD].forEach((stat: number) => expect(enemy.getStatStage(stat)).toBeLessThan(0)); + [ Stat.ACC, Stat.DEF, Stat.EVA, Stat.SPATK, Stat.SPDEF, Stat.SPD ].forEach((stat: number) => expect(enemy.getStatStage(stat)).toBeLessThan(0)); }); }); diff --git a/src/test/abilities/ice_face.test.ts b/src/test/abilities/ice_face.test.ts index fbc660c27c2..1c7f7bd6093 100644 --- a/src/test/abilities/ice_face.test.ts +++ b/src/test/abilities/ice_face.test.ts @@ -1,3 +1,4 @@ +import { BattlerIndex } from "#app/battle"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MoveEndPhase } from "#app/phases/move-end-phase"; import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; @@ -32,11 +33,11 @@ describe("Abilities - Ice Face", () => { game.override.battleType("single"); game.override.enemySpecies(Species.EISCUE); game.override.enemyAbility(Abilities.ICE_FACE); - game.override.moveset([Moves.TACKLE, Moves.ICE_BEAM, Moves.TOXIC_THREAD, Moves.HAIL]); + game.override.moveset([ Moves.TACKLE, Moves.ICE_BEAM, Moves.TOXIC_THREAD, Moves.HAIL ]); }); it("takes no damage from physical move and transforms to Noice", async () => { - await game.startBattle([Species.HITMONLEE]); + await game.classicMode.startBattle([ Species.HITMONLEE ]); game.move.select(Moves.TACKLE); @@ -50,9 +51,9 @@ describe("Abilities - Ice Face", () => { }); it("takes no damage from the first hit of multihit physical move and transforms to Noice", async () => { - game.override.moveset([Moves.SURGING_STRIKES]); + game.override.moveset([ Moves.SURGING_STRIKES ]); game.override.enemyLevel(1); - await game.startBattle([Species.HITMONLEE]); + await game.classicMode.startBattle([ Species.HITMONLEE ]); game.move.select(Moves.SURGING_STRIKES); @@ -78,7 +79,7 @@ describe("Abilities - Ice Face", () => { }); it("takes damage from special moves", async () => { - await game.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.ICE_BEAM); @@ -92,7 +93,7 @@ describe("Abilities - Ice Face", () => { }); it("takes effects from status moves", async () => { - await game.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.TOXIC_THREAD); @@ -105,10 +106,10 @@ describe("Abilities - Ice Face", () => { }); it("transforms to Ice Face when Hail or Snow starts", async () => { - game.override.moveset([Moves.QUICK_ATTACK]); - game.override.enemyMoveset([Moves.HAIL, Moves.HAIL, Moves.HAIL, Moves.HAIL]); + game.override.moveset([ Moves.QUICK_ATTACK ]); + game.override.enemyMoveset([ Moves.HAIL, Moves.HAIL, Moves.HAIL, Moves.HAIL ]); - await game.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.QUICK_ATTACK); @@ -127,10 +128,10 @@ describe("Abilities - Ice Face", () => { }); it("transforms to Ice Face when summoned on arena with active Snow or Hail", async () => { - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); - game.override.moveset([Moves.SNOWSCAPE]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); + game.override.moveset([ Moves.SNOWSCAPE ]); - await game.startBattle([Species.EISCUE, Species.NINJASK]); + await game.classicMode.startBattle([ Species.EISCUE, Species.NINJASK ]); game.move.select(Moves.SNOWSCAPE); @@ -155,9 +156,9 @@ describe("Abilities - Ice Face", () => { it("will not revert to its Ice Face if there is already Hail when it changes into Noice", async () => { game.override.enemySpecies(Species.SHUCKLE); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); - await game.startBattle([Species.EISCUE]); + await game.classicMode.startBattle([ Species.EISCUE ]); game.move.select(Moves.HAIL); const eiscue = game.scene.getPlayerPokemon()!; @@ -174,9 +175,9 @@ describe("Abilities - Ice Face", () => { }); it("persists form change when switched out", async () => { - game.override.enemyMoveset([Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK]); + game.override.enemyMoveset([ Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK ]); - await game.startBattle([Species.EISCUE, Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.EISCUE, Species.MAGIKARP ]); game.move.select(Moves.ICE_BEAM); @@ -205,7 +206,7 @@ describe("Abilities - Ice Face", () => { [Species.EISCUE]: noiceForm, }); - await game.startBattle([Species.EISCUE]); + await game.classicMode.startBattle([ Species.EISCUE ]); const eiscue = game.scene.getPlayerPokemon()!; @@ -222,10 +223,23 @@ describe("Abilities - Ice Face", () => { expect(eiscue.getTag(BattlerTagType.ICE_FACE)).not.toBe(undefined); }); - it("cannot be suppressed", async () => { - game.override.moveset([Moves.GASTRO_ACID]); + it("doesn't trigger if user is behind a substitute", async () => { + game.override + .enemyMoveset(Moves.SUBSTITUTE) + .moveset(Moves.POWER_TRIP); + await game.classicMode.startBattle(); - await game.startBattle([Species.MAGIKARP]); + game.move.select(Moves.POWER_TRIP); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.toNextTurn(); + + expect(game.scene.getEnemyPokemon()!.formIndex).toBe(icefaceForm); + }); + + it("cannot be suppressed", async () => { + game.override.moveset([ Moves.GASTRO_ACID ]); + + await game.classicMode.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.GASTRO_ACID); @@ -239,9 +253,9 @@ describe("Abilities - Ice Face", () => { }); it("cannot be swapped with another ability", async () => { - game.override.moveset([Moves.SKILL_SWAP]); + game.override.moveset([ Moves.SKILL_SWAP ]); - await game.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.SKILL_SWAP); @@ -257,7 +271,7 @@ describe("Abilities - Ice Face", () => { it("cannot be copied", async () => { game.override.ability(Abilities.TRACE); - await game.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.SIMPLE_BEAM); diff --git a/src/test/abilities/imposter.test.ts b/src/test/abilities/imposter.test.ts index 27673564aaa..b7b8e0c5cca 100644 --- a/src/test/abilities/imposter.test.ts +++ b/src/test/abilities/imposter.test.ts @@ -76,7 +76,7 @@ describe("Abilities - Imposter", () => { }, 20000); it("should copy in-battle overridden stats", async () => { - game.override.enemyMoveset([Moves.POWER_SPLIT]); + game.override.enemyMoveset([ Moves.POWER_SPLIT ]); await game.startBattle([ Species.DITTO diff --git a/src/test/abilities/intimidate.test.ts b/src/test/abilities/intimidate.test.ts index d4c097022df..d5a37d06593 100644 --- a/src/test/abilities/intimidate.test.ts +++ b/src/test/abilities/intimidate.test.ts @@ -34,7 +34,7 @@ describe("Abilities - Intimidate", () => { }); it("should lower ATK stat stage by 1 of enemy Pokemon on entry and player switch", async () => { - await game.classicMode.runToSummon([Species.MIGHTYENA, Species.POOCHYENA]); + await game.classicMode.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA ]); game.onNextPrompt( "CheckSwitchPhase", Mode.CONFIRM, @@ -66,7 +66,7 @@ describe("Abilities - Intimidate", () => { it("should lower ATK stat stage by 1 for every enemy Pokemon in a double battle on entry", async () => { game.override.battleType("double") .startingWave(3); - await game.classicMode.runToSummon([Species.MIGHTYENA, Species.POOCHYENA]); + await game.classicMode.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA ]); game.onNextPrompt( "CheckSwitchPhase", Mode.CONFIRM, @@ -89,7 +89,7 @@ describe("Abilities - Intimidate", () => { it("should not activate again if there is no switch or new entry", async () => { game.override.startingWave(2); - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); await game.classicMode.startBattle([ Species.MIGHTYENA, Species.POOCHYENA ]); const playerPokemon = game.scene.getPlayerPokemon()!; @@ -106,8 +106,8 @@ describe("Abilities - Intimidate", () => { }, 20000); it("should lower ATK stat stage by 1 for every switch", async () => { - game.override.moveset([Moves.SPLASH]) - .enemyMoveset([Moves.VOLT_SWITCH]) + game.override.moveset([ Moves.SPLASH ]) + .enemyMoveset([ Moves.VOLT_SWITCH ]) .startingWave(5); await game.classicMode.startBattle([ Species.MIGHTYENA, Species.POOCHYENA ]); diff --git a/src/test/abilities/libero.test.ts b/src/test/abilities/libero.test.ts index f429d9ffc72..aac1cb16d97 100644 --- a/src/test/abilities/libero.test.ts +++ b/src/test/abilities/libero.test.ts @@ -13,7 +13,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; - describe("Abilities - Libero", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -34,15 +33,15 @@ describe("Abilities - Libero", () => { game.override.ability(Abilities.LIBERO); game.override.startingLevel(100); game.override.enemySpecies(Species.RATTATA); - game.override.enemyMoveset([Moves.ENDURE, Moves.ENDURE, Moves.ENDURE, Moves.ENDURE]); + game.override.enemyMoveset([ Moves.ENDURE, Moves.ENDURE, Moves.ENDURE, Moves.ENDURE ]); }); test( "ability applies and changes a pokemon's type", async () => { - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -57,9 +56,9 @@ describe("Abilities - Libero", () => { test.skip( "ability applies only once per switch in", async () => { - game.override.moveset([Moves.SPLASH, Moves.AGILITY]); + game.override.moveset([ Moves.SPLASH, Moves.AGILITY ]); - await game.startBattle([Species.MAGIKARP, Species.BULBASAUR]); + await game.startBattle([ Species.MAGIKARP, Species.BULBASAUR ]); let leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -96,9 +95,9 @@ describe("Abilities - Libero", () => { test( "ability applies correctly even if the pokemon's move has a variable type", async () => { - game.override.moveset([Moves.WEATHER_BALL]); + game.override.moveset([ Moves.WEATHER_BALL ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -118,10 +117,10 @@ describe("Abilities - Libero", () => { test( "ability applies correctly even if the type has changed by another ability", async () => { - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.passiveAbility(Abilities.REFRIGERATE); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -140,9 +139,9 @@ describe("Abilities - Libero", () => { test( "ability applies correctly even if the pokemon's move calls another move", async () => { - game.override.moveset([Moves.NATURE_POWER]); + game.override.moveset([ Moves.NATURE_POWER ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -158,9 +157,9 @@ describe("Abilities - Libero", () => { test( "ability applies correctly even if the pokemon's move is delayed / charging", async () => { - game.override.moveset([Moves.DIG]); + game.override.moveset([ Moves.DIG ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -175,10 +174,10 @@ describe("Abilities - Libero", () => { test( "ability applies correctly even if the pokemon's move misses", async () => { - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.enemyMoveset(Moves.SPLASH); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -196,10 +195,10 @@ describe("Abilities - Libero", () => { test( "ability applies correctly even if the pokemon's move is protected against", async () => { - game.override.moveset([Moves.TACKLE]); - game.override.enemyMoveset([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]); + game.override.moveset([ Moves.TACKLE ]); + game.override.enemyMoveset([ Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -214,10 +213,10 @@ describe("Abilities - Libero", () => { test( "ability applies correctly even if the pokemon's move fails because of type immunity", async () => { - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.enemySpecies(Species.GASTLY); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -232,14 +231,14 @@ describe("Abilities - Libero", () => { test( "ability is not applied if pokemon's type is the same as the move's type", async () => { - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - leadPokemon.summonData.types = [allMoves[Moves.SPLASH].type]; + leadPokemon.summonData.types = [ allMoves[Moves.SPLASH].type ]; game.move.select(Moves.SPLASH); await game.phaseInterceptor.to(TurnEndPhase); @@ -250,9 +249,9 @@ describe("Abilities - Libero", () => { test( "ability is not applied if pokemon is terastallized", async () => { - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -269,9 +268,9 @@ describe("Abilities - Libero", () => { test( "ability is not applied if pokemon uses struggle", async () => { - game.override.moveset([Moves.STRUGGLE]); + game.override.moveset([ Moves.STRUGGLE ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -286,9 +285,9 @@ describe("Abilities - Libero", () => { test( "ability is not applied if the pokemon's move fails", async () => { - game.override.moveset([Moves.BURN_UP]); + game.override.moveset([ Moves.BURN_UP ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -303,10 +302,10 @@ describe("Abilities - Libero", () => { test( "ability applies correctly even if the pokemon's Trick-or-Treat fails", async () => { - game.override.moveset([Moves.TRICK_OR_TREAT]); + game.override.moveset([ Moves.TRICK_OR_TREAT ]); game.override.enemySpecies(Species.GASTLY); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -321,9 +320,9 @@ describe("Abilities - Libero", () => { test( "ability applies correctly and the pokemon curses itself", async () => { - game.override.moveset([Moves.CURSE]); + game.override.moveset([ Moves.CURSE ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); diff --git a/src/test/abilities/magic_guard.test.ts b/src/test/abilities/magic_guard.test.ts index dd8b83f7601..614f983e76e 100644 --- a/src/test/abilities/magic_guard.test.ts +++ b/src/test/abilities/magic_guard.test.ts @@ -30,7 +30,7 @@ describe("Abilities - Magic Guard", () => { /** Player Pokemon overrides */ game.override.ability(Abilities.MAGIC_GUARD); - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); game.override.startingLevel(100); /** Enemy Pokemon overrides */ @@ -47,7 +47,7 @@ describe("Abilities - Magic Guard", () => { async () => { game.override.weather(WeatherType.SANDSTORM); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -74,7 +74,7 @@ describe("Abilities - Magic Guard", () => { //Toxic keeps track of the turn counters -> important that Magic Guard keeps track of post-Toxic turns game.override.statusEffect(StatusEffect.POISON); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -95,10 +95,10 @@ describe("Abilities - Magic Guard", () => { it( "ability effect should not persist when the ability is replaced", async () => { - game.override.enemyMoveset([Moves.WORRY_SEED, Moves.WORRY_SEED, Moves.WORRY_SEED, Moves.WORRY_SEED]); + game.override.enemyMoveset([ Moves.WORRY_SEED, Moves.WORRY_SEED, Moves.WORRY_SEED, Moves.WORRY_SEED ]); game.override.statusEffect(StatusEffect.POISON); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -120,7 +120,7 @@ describe("Abilities - Magic Guard", () => { game.override.enemyStatusEffect(StatusEffect.BURN); game.override.enemyAbility(Abilities.MAGIC_GUARD); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.SPLASH); @@ -144,7 +144,7 @@ describe("Abilities - Magic Guard", () => { game.override.enemyStatusEffect(StatusEffect.TOXIC); game.override.enemyAbility(Abilities.MAGIC_GUARD); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.SPLASH); @@ -173,7 +173,7 @@ describe("Abilities - Magic Guard", () => { const newTag = getArenaTag(ArenaTagType.SPIKES, 5, Moves.SPIKES, 0, 0, ArenaTagSide.BOTH)!; game.scene.arena.tags.push(newTag); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.SPLASH); @@ -199,7 +199,7 @@ describe("Abilities - Magic Guard", () => { game.scene.arena.tags.push(playerTag); game.scene.arena.tags.push(enemyTag); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.SPLASH); @@ -223,8 +223,8 @@ describe("Abilities - Magic Guard", () => { it("Magic Guard prevents against damage from volatile status effects", async () => { - await game.startBattle([Species.DUSKULL]); - game.override.moveset([Moves.CURSE]); + await game.startBattle([ Species.DUSKULL ]); + game.override.moveset([ Moves.CURSE ]); game.override.enemyAbility(Abilities.MAGIC_GUARD); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -248,8 +248,8 @@ describe("Abilities - Magic Guard", () => { ); it("Magic Guard prevents crash damage", async () => { - game.override.moveset([Moves.HIGH_JUMP_KICK]); - await game.startBattle([Species.MAGIKARP]); + game.override.moveset([ Moves.HIGH_JUMP_KICK ]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -267,8 +267,8 @@ describe("Abilities - Magic Guard", () => { ); it("Magic Guard prevents damage from recoil", async () => { - game.override.moveset([Moves.TAKE_DOWN]); - await game.startBattle([Species.MAGIKARP]); + game.override.moveset([ Moves.TAKE_DOWN ]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -285,8 +285,8 @@ describe("Abilities - Magic Guard", () => { ); it("Magic Guard does not prevent damage from Struggle's recoil", async () => { - game.override.moveset([Moves.STRUGGLE]); - await game.startBattle([Species.MAGIKARP]); + game.override.moveset([ Moves.STRUGGLE ]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -304,8 +304,8 @@ describe("Abilities - Magic Guard", () => { //This tests different move attributes than the recoil tests above it("Magic Guard prevents self-damage from attacking moves", async () => { - game.override.moveset([Moves.STEEL_BEAM]); - await game.startBattle([Species.MAGIKARP]); + game.override.moveset([ Moves.STEEL_BEAM ]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -332,8 +332,8 @@ describe("Abilities - Magic Guard", () => { */ it("Magic Guard does not prevent self-damage from non-attacking moves", async () => { - game.override.moveset([Moves.BELLY_DRUM]); - await game.startBattle([Species.MAGIKARP]); + game.override.moveset([ Moves.BELLY_DRUM ]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -353,10 +353,10 @@ describe("Abilities - Magic Guard", () => { //Tests the ability Bad Dreams game.override.statusEffect(StatusEffect.SLEEP); //enemy pokemon is given Spore just in case player pokemon somehow awakens during test - game.override.enemyMoveset([Moves.SPORE, Moves.SPORE, Moves.SPORE, Moves.SPORE]); + game.override.enemyMoveset([ Moves.SPORE, Moves.SPORE, Moves.SPORE, Moves.SPORE ]); game.override.enemyAbility(Abilities.BAD_DREAMS); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -376,10 +376,10 @@ describe("Abilities - Magic Guard", () => { it("Magic Guard prevents damage from abilities with PostFaintContactDamageAbAttr", async () => { //Tests the abilities Innards Out/Aftermath - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.enemyAbility(Abilities.AFTERMATH); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -401,10 +401,10 @@ describe("Abilities - Magic Guard", () => { it("Magic Guard prevents damage from abilities with PostDefendContactDamageAbAttr", async () => { //Tests the abilities Iron Barbs/Rough Skin - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.enemyAbility(Abilities.IRON_BARBS); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -425,10 +425,10 @@ describe("Abilities - Magic Guard", () => { it("Magic Guard prevents damage from abilities with ReverseDrainAbAttr", async () => { //Tests the ability Liquid Ooze - game.override.moveset([Moves.ABSORB]); + game.override.moveset([ Moves.ABSORB ]); game.override.enemyAbility(Abilities.LIQUID_OOZE); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -452,7 +452,7 @@ describe("Abilities - Magic Guard", () => { game.override.passiveAbility(Abilities.SOLAR_POWER); game.override.weather(WeatherType.SUNNY); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.SPLASH); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/abilities/mycelium_might.test.ts b/src/test/abilities/mycelium_might.test.ts index d8947935880..0c8e7b5a703 100644 --- a/src/test/abilities/mycelium_might.test.ts +++ b/src/test/abilities/mycelium_might.test.ts @@ -28,9 +28,9 @@ describe("Abilities - Mycelium Might", () => { game.override.disableCrits(); game.override.enemySpecies(Species.SHUCKLE); game.override.enemyAbility(Abilities.CLEAR_BODY); - game.override.enemyMoveset([Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK]); + game.override.enemyMoveset([ Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK ]); game.override.ability(Abilities.MYCELIUM_MIGHT); - game.override.moveset([Moves.QUICK_ATTACK, Moves.BABY_DOLL_EYES]); + game.override.moveset([ Moves.QUICK_ATTACK, Moves.BABY_DOLL_EYES ]); }); /** @@ -41,7 +41,7 @@ describe("Abilities - Mycelium Might", () => { **/ it("will move last in its priority bracket and ignore protective abilities", async () => { - await game.startBattle([Species.REGIELEKI]); + await game.startBattle([ Species.REGIELEKI ]); const enemyPokemon = game.scene.getEnemyPokemon(); const playerIndex = game.scene.getPlayerPokemon()?.getBattlerIndex(); @@ -55,8 +55,8 @@ describe("Abilities - Mycelium Might", () => { const commandOrder = phase.getCommandOrder(); // The opponent Pokemon (without Mycelium Might) goes first despite having lower speed than the player Pokemon. // The player Pokemon (with Mycelium Might) goes last despite having higher speed than the opponent. - expect(speedOrder).toEqual([playerIndex, enemyIndex]); - expect(commandOrder).toEqual([enemyIndex, playerIndex]); + expect(speedOrder).toEqual([ playerIndex, enemyIndex ]); + expect(commandOrder).toEqual([ enemyIndex, playerIndex ]); await game.phaseInterceptor.to(TurnEndPhase); // Despite the opponent's ability (Clear Body), its ATK stat stage is still reduced. @@ -64,8 +64,8 @@ describe("Abilities - Mycelium Might", () => { }, 20000); it("will still go first if a status move that is in a higher priority bracket than the opponent's move is used", async () => { - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); - await game.startBattle([Species.REGIELEKI]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); + await game.startBattle([ Species.REGIELEKI ]); const enemyPokemon = game.scene.getEnemyPokemon(); const playerIndex = game.scene.getPlayerPokemon()?.getBattlerIndex(); @@ -79,15 +79,15 @@ describe("Abilities - Mycelium Might", () => { const commandOrder = phase.getCommandOrder(); // The player Pokemon (with M.M.) goes first because its move is still within a higher priority bracket than its opponent. // The enemy Pokemon goes second because its move is in a lower priority bracket. - expect(speedOrder).toEqual([playerIndex, enemyIndex]); - expect(commandOrder).toEqual([playerIndex, enemyIndex]); + expect(speedOrder).toEqual([ playerIndex, enemyIndex ]); + expect(commandOrder).toEqual([ playerIndex, enemyIndex ]); await game.phaseInterceptor.to(TurnEndPhase); // Despite the opponent's ability (Clear Body), its ATK stat stage is still reduced. expect(enemyPokemon?.getStatStage(Stat.ATK)).toBe(-1); }, 20000); it("will not affect non-status moves", async () => { - await game.startBattle([Species.REGIELEKI]); + await game.startBattle([ Species.REGIELEKI ]); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); @@ -101,7 +101,7 @@ describe("Abilities - Mycelium Might", () => { // The player Pokemon (with M.M.) goes first because it has a higher speed and did not use a status move. // The enemy Pokemon (without M.M.) goes second because its speed is lower. // This means that the commandOrder should be identical to the speedOrder - expect(speedOrder).toEqual([playerIndex, enemyIndex]); - expect(commandOrder).toEqual([playerIndex, enemyIndex]); + expect(speedOrder).toEqual([ playerIndex, enemyIndex ]); + expect(commandOrder).toEqual([ playerIndex, enemyIndex ]); }, 20000); }); diff --git a/src/test/abilities/parental_bond.test.ts b/src/test/abilities/parental_bond.test.ts index 22c9d8028be..993a5eb8344 100644 --- a/src/test/abilities/parental_bond.test.ts +++ b/src/test/abilities/parental_bond.test.ts @@ -11,7 +11,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Abilities - Parental Bond", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -41,9 +40,9 @@ describe("Abilities - Parental Bond", () => { it( "should add second strike to attack move", async () => { - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -68,10 +67,10 @@ describe("Abilities - Parental Bond", () => { it( "should apply secondary effects to both strikes", async () => { - game.override.moveset([Moves.POWER_UP_PUNCH]); + game.override.moveset([ Moves.POWER_UP_PUNCH ]); game.override.enemySpecies(Species.AMOONGUSS); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -87,9 +86,9 @@ describe("Abilities - Parental Bond", () => { it( "should not apply to Status moves", async () => { - game.override.moveset([Moves.BABY_DOLL_EYES]); + game.override.moveset([ Moves.BABY_DOLL_EYES ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -104,9 +103,9 @@ describe("Abilities - Parental Bond", () => { it( "should not apply to multi-hit moves", async () => { - game.override.moveset([Moves.DOUBLE_HIT]); + game.override.moveset([ Moves.DOUBLE_HIT ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -122,9 +121,9 @@ describe("Abilities - Parental Bond", () => { it( "should not apply to self-sacrifice moves", async () => { - game.override.moveset([Moves.SELF_DESTRUCT]); + game.override.moveset([ Moves.SELF_DESTRUCT ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -139,9 +138,9 @@ describe("Abilities - Parental Bond", () => { it( "should not apply to Rollout", async () => { - game.override.moveset([Moves.ROLLOUT]); + game.override.moveset([ Moves.ROLLOUT ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -157,9 +156,9 @@ describe("Abilities - Parental Bond", () => { it( "should not apply multiplier to fixed-damage moves", async () => { - game.override.moveset([Moves.DRAGON_RAGE]); + game.override.moveset([ Moves.DRAGON_RAGE ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -173,10 +172,10 @@ describe("Abilities - Parental Bond", () => { it( "should not apply multiplier to counter moves", async () => { - game.override.moveset([Moves.COUNTER]); - game.override.enemyMoveset([Moves.TACKLE]); + game.override.moveset([ Moves.COUNTER ]); + game.override.enemyMoveset([ Moves.TACKLE ]); - await game.classicMode.startBattle([Species.SHUCKLE]); + await game.classicMode.startBattle([ Species.SHUCKLE ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -196,10 +195,10 @@ describe("Abilities - Parental Bond", () => { "should not apply to multi-target moves", async () => { game.override.battleType("double"); - game.override.moveset([Moves.EARTHQUAKE]); + game.override.moveset([ Moves.EARTHQUAKE ]); game.override.passiveAbility(Abilities.LEVITATE); - await game.classicMode.startBattle([Species.MAGIKARP, Species.FEEBAS]); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.FEEBAS ]); const playerPokemon = game.scene.getPlayerField(); @@ -215,9 +214,9 @@ describe("Abilities - Parental Bond", () => { it( "should apply to multi-target moves when hitting only one target", async () => { - game.override.moveset([Moves.EARTHQUAKE]); + game.override.moveset([ Moves.EARTHQUAKE ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -231,9 +230,9 @@ describe("Abilities - Parental Bond", () => { it( "should only trigger post-target move effects once", async () => { - game.override.moveset([Moves.MIND_BLOWN]); + game.override.moveset([ Moves.MIND_BLOWN ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -253,9 +252,9 @@ describe("Abilities - Parental Bond", () => { it( "Burn Up only removes type after the second strike", async () => { - game.override.moveset([Moves.BURN_UP]); + game.override.moveset([ Moves.BURN_UP ]); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -277,10 +276,10 @@ describe("Abilities - Parental Bond", () => { it( "Moves boosted by this ability and Multi-Lens should strike 4 times", async () => { - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -295,10 +294,10 @@ describe("Abilities - Parental Bond", () => { it( "Super Fang boosted by this ability and Multi-Lens should strike twice", async () => { - game.override.moveset([Moves.SUPER_FANG]); + game.override.moveset([ Moves.SUPER_FANG ]); game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -319,10 +318,10 @@ describe("Abilities - Parental Bond", () => { it( "Seismic Toss boosted by this ability and Multi-Lens should strike twice", async () => { - game.override.moveset([Moves.SEISMIC_TOSS]); + game.override.moveset([ Moves.SEISMIC_TOSS ]); game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -345,9 +344,9 @@ describe("Abilities - Parental Bond", () => { it( "Hyper Beam boosted by this ability should strike twice, then recharge", async () => { - game.override.moveset([Moves.HYPER_BEAM]); + game.override.moveset([ Moves.HYPER_BEAM ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -368,9 +367,9 @@ describe("Abilities - Parental Bond", () => { it( "Anchor Shot boosted by this ability should only trap the target after the second hit", async () => { - game.override.moveset([Moves.ANCHOR_SHOT]); + game.override.moveset([ Moves.ANCHOR_SHOT ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -395,9 +394,9 @@ describe("Abilities - Parental Bond", () => { it( "Smack Down boosted by this ability should only ground the target after the second hit", async () => { - game.override.moveset([Moves.SMACK_DOWN]); + game.override.moveset([ Moves.SMACK_DOWN ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -419,9 +418,9 @@ describe("Abilities - Parental Bond", () => { it( "U-turn boosted by this ability should strike twice before forcing a switch", async () => { - game.override.moveset([Moves.U_TURN]); + game.override.moveset([ Moves.U_TURN ]); - await game.classicMode.startBattle([Species.MAGIKARP, Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -439,9 +438,9 @@ describe("Abilities - Parental Bond", () => { it( "Wake-Up Slap boosted by this ability should only wake up the target after the second hit", async () => { - game.override.moveset([Moves.WAKE_UP_SLAP]).enemyStatusEffect(StatusEffect.SLEEP); + game.override.moveset([ Moves.WAKE_UP_SLAP ]).enemyStatusEffect(StatusEffect.SLEEP); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -463,10 +462,10 @@ describe("Abilities - Parental Bond", () => { it( "should not cause user to hit into King's Shield more than once", async () => { - game.override.moveset([Moves.TACKLE]); - game.override.enemyMoveset([Moves.KINGS_SHIELD]); + game.override.moveset([ Moves.TACKLE ]); + game.override.enemyMoveset([ Moves.KINGS_SHIELD ]); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -481,10 +480,10 @@ describe("Abilities - Parental Bond", () => { it( "should not cause user to hit into Storm Drain more than once", async () => { - game.override.moveset([Moves.WATER_GUN]); + game.override.moveset([ Moves.WATER_GUN ]); game.override.enemyAbility(Abilities.STORM_DRAIN); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -500,11 +499,11 @@ describe("Abilities - Parental Bond", () => { "should not apply to multi-target moves with Multi-Lens", async () => { game.override.battleType("double"); - game.override.moveset([Moves.EARTHQUAKE, Moves.SPLASH]); + game.override.moveset([ Moves.EARTHQUAKE, Moves.SPLASH ]); game.override.passiveAbility(Abilities.LEVITATE); game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); - await game.classicMode.startBattle([Species.MAGIKARP, Species.FEEBAS]); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.FEEBAS ]); const enemyPokemon = game.scene.getEnemyField(); diff --git a/src/test/abilities/pastel_veil.test.ts b/src/test/abilities/pastel_veil.test.ts index 31490aab143..660ff2616e9 100644 --- a/src/test/abilities/pastel_veil.test.ts +++ b/src/test/abilities/pastel_veil.test.ts @@ -27,14 +27,14 @@ describe("Abilities - Pastel Veil", () => { game = new GameManager(phaserGame); game.override .battleType("double") - .moveset([Moves.TOXIC_THREAD, Moves.SPLASH]) + .moveset([ Moves.TOXIC_THREAD, Moves.SPLASH ]) .enemyAbility(Abilities.BALL_FETCH) .enemySpecies(Species.SUNKERN) .enemyMoveset(Moves.SPLASH); }); it("prevents the user and its allies from being afflicted by poison", async () => { - await game.startBattle([Species.MAGIKARP, Species.GALAR_PONYTA]); + await game.startBattle([ Species.MAGIKARP, Species.GALAR_PONYTA ]); const ponyta = game.scene.getPlayerField()[1]; const magikarp = game.scene.getPlayerField()[0]; ponyta.abilityIndex = 1; @@ -50,7 +50,7 @@ describe("Abilities - Pastel Veil", () => { }); it("it heals the poisoned status condition of allies if user is sent out into battle", async () => { - await game.startBattle([Species.MAGIKARP, Species.FEEBAS, Species.GALAR_PONYTA]); + await game.startBattle([ Species.MAGIKARP, Species.FEEBAS, Species.GALAR_PONYTA ]); const ponyta = game.scene.getParty()[2]; const magikarp = game.scene.getPlayerField()[0]; ponyta.abilityIndex = 1; diff --git a/src/test/abilities/power_construct.test.ts b/src/test/abilities/power_construct.test.ts index 94cee82fb4a..1a9e7d4818a 100644 --- a/src/test/abilities/power_construct.test.ts +++ b/src/test/abilities/power_construct.test.ts @@ -8,7 +8,6 @@ import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - describe("Abilities - POWER CONSTRUCT", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -28,12 +27,12 @@ describe("Abilities - POWER CONSTRUCT", () => { const moveToUse = Moves.SPLASH; game.override.battleType("single"); game.override.ability(Abilities.POWER_CONSTRUCT); - game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.moveset([ moveToUse ]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); }); test( - "check if fainted pokemon switches to base form on arena reset", + "check if fainted 50% Power Construct Pokemon switches to base form on arena reset", async () => { const baseForm = 2, completeForm = 4; @@ -42,7 +41,37 @@ describe("Abilities - POWER CONSTRUCT", () => { [Species.ZYGARDE]: completeForm, }); - await game.startBattle([Species.MAGIKARP, Species.ZYGARDE]); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.ZYGARDE ]); + + const zygarde = game.scene.getParty().find((p) => p.species.speciesId === Species.ZYGARDE); + expect(zygarde).not.toBe(undefined); + expect(zygarde!.formIndex).toBe(completeForm); + + zygarde!.hp = 0; + zygarde!.status = new Status(StatusEffect.FAINT); + expect(zygarde!.isFainted()).toBe(true); + + game.move.select(Moves.SPLASH); + await game.doKillOpponents(); + await game.phaseInterceptor.to(TurnEndPhase); + game.doSelectModifier(); + await game.phaseInterceptor.to(QuietFormChangePhase); + + expect(zygarde!.formIndex).toBe(baseForm); + }, + ); + + test( + "check if fainted 10% Power Construct Pokemon switches to base form on arena reset", + async () => { + const baseForm = 3, + completeForm = 5; + game.override.startingWave(4); + game.override.starterForms({ + [Species.ZYGARDE]: completeForm, + }); + + await game.classicMode.startBattle([ Species.MAGIKARP, Species.ZYGARDE ]); const zygarde = game.scene.getParty().find((p) => p.species.speciesId === Species.ZYGARDE); expect(zygarde).not.toBe(undefined); diff --git a/src/test/abilities/power_spot.test.ts b/src/test/abilities/power_spot.test.ts index 6d349a1a3f9..a566c2277c3 100644 --- a/src/test/abilities/power_spot.test.ts +++ b/src/test/abilities/power_spot.test.ts @@ -27,7 +27,7 @@ describe("Abilities - Power Spot", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("double"); - game.override.moveset([Moves.TACKLE, Moves.BREAKING_SWIPE, Moves.SPLASH, Moves.DAZZLING_GLEAM]); + game.override.moveset([ Moves.TACKLE, Moves.BREAKING_SWIPE, Moves.SPLASH, Moves.DAZZLING_GLEAM ]); game.override.enemyMoveset(Moves.SPLASH); game.override.enemySpecies(Species.SHUCKLE); game.override.enemyAbility(Abilities.BALL_FETCH); @@ -39,7 +39,7 @@ describe("Abilities - Power Spot", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.startBattle([Species.REGIELEKI, Species.STONJOURNER]); + await game.startBattle([ Species.REGIELEKI, Species.STONJOURNER ]); game.move.select(Moves.DAZZLING_GLEAM); game.move.select(Moves.SPLASH, 1); await game.phaseInterceptor.to(MoveEffectPhase); @@ -53,7 +53,7 @@ describe("Abilities - Power Spot", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.startBattle([Species.REGIELEKI, Species.STONJOURNER]); + await game.startBattle([ Species.REGIELEKI, Species.STONJOURNER ]); game.move.select(Moves.BREAKING_SWIPE); game.move.select(Moves.SPLASH, 1); await game.phaseInterceptor.to(MoveEffectPhase); @@ -67,7 +67,7 @@ describe("Abilities - Power Spot", () => { vi.spyOn(moveToCheck, "calculateBattlePower"); - await game.startBattle([Species.STONJOURNER, Species.REGIELEKI]); + await game.startBattle([ Species.STONJOURNER, Species.REGIELEKI ]); game.move.select(Moves.BREAKING_SWIPE); game.move.select(Moves.SPLASH, 1); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/abilities/protean.test.ts b/src/test/abilities/protean.test.ts index 8479a293722..5f86ec4c6e6 100644 --- a/src/test/abilities/protean.test.ts +++ b/src/test/abilities/protean.test.ts @@ -13,7 +13,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; - describe("Abilities - Protean", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -34,15 +33,15 @@ describe("Abilities - Protean", () => { game.override.ability(Abilities.PROTEAN); game.override.startingLevel(100); game.override.enemySpecies(Species.RATTATA); - game.override.enemyMoveset([Moves.ENDURE, Moves.ENDURE, Moves.ENDURE, Moves.ENDURE]); + game.override.enemyMoveset([ Moves.ENDURE, Moves.ENDURE, Moves.ENDURE, Moves.ENDURE ]); }); test( "ability applies and changes a pokemon's type", async () => { - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -57,9 +56,9 @@ describe("Abilities - Protean", () => { test.skip( "ability applies only once per switch in", async () => { - game.override.moveset([Moves.SPLASH, Moves.AGILITY]); + game.override.moveset([ Moves.SPLASH, Moves.AGILITY ]); - await game.startBattle([Species.MAGIKARP, Species.BULBASAUR]); + await game.startBattle([ Species.MAGIKARP, Species.BULBASAUR ]); let leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -96,9 +95,9 @@ describe("Abilities - Protean", () => { test( "ability applies correctly even if the pokemon's move has a variable type", async () => { - game.override.moveset([Moves.WEATHER_BALL]); + game.override.moveset([ Moves.WEATHER_BALL ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -118,10 +117,10 @@ describe("Abilities - Protean", () => { test( "ability applies correctly even if the type has changed by another ability", async () => { - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.passiveAbility(Abilities.REFRIGERATE); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -140,9 +139,9 @@ describe("Abilities - Protean", () => { test( "ability applies correctly even if the pokemon's move calls another move", async () => { - game.override.moveset([Moves.NATURE_POWER]); + game.override.moveset([ Moves.NATURE_POWER ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -158,9 +157,9 @@ describe("Abilities - Protean", () => { test( "ability applies correctly even if the pokemon's move is delayed / charging", async () => { - game.override.moveset([Moves.DIG]); + game.override.moveset([ Moves.DIG ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -175,10 +174,10 @@ describe("Abilities - Protean", () => { test( "ability applies correctly even if the pokemon's move misses", async () => { - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.enemyMoveset(Moves.SPLASH); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -196,10 +195,10 @@ describe("Abilities - Protean", () => { test( "ability applies correctly even if the pokemon's move is protected against", async () => { - game.override.moveset([Moves.TACKLE]); - game.override.enemyMoveset([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]); + game.override.moveset([ Moves.TACKLE ]); + game.override.enemyMoveset([ Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -214,10 +213,10 @@ describe("Abilities - Protean", () => { test( "ability applies correctly even if the pokemon's move fails because of type immunity", async () => { - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.enemySpecies(Species.GASTLY); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -232,14 +231,14 @@ describe("Abilities - Protean", () => { test( "ability is not applied if pokemon's type is the same as the move's type", async () => { - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); - leadPokemon.summonData.types = [allMoves[Moves.SPLASH].type]; + leadPokemon.summonData.types = [ allMoves[Moves.SPLASH].type ]; game.move.select(Moves.SPLASH); await game.phaseInterceptor.to(TurnEndPhase); @@ -250,9 +249,9 @@ describe("Abilities - Protean", () => { test( "ability is not applied if pokemon is terastallized", async () => { - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -269,9 +268,9 @@ describe("Abilities - Protean", () => { test( "ability is not applied if pokemon uses struggle", async () => { - game.override.moveset([Moves.STRUGGLE]); + game.override.moveset([ Moves.STRUGGLE ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -286,9 +285,9 @@ describe("Abilities - Protean", () => { test( "ability is not applied if the pokemon's move fails", async () => { - game.override.moveset([Moves.BURN_UP]); + game.override.moveset([ Moves.BURN_UP ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -303,10 +302,10 @@ describe("Abilities - Protean", () => { test( "ability applies correctly even if the pokemon's Trick-or-Treat fails", async () => { - game.override.moveset([Moves.TRICK_OR_TREAT]); + game.override.moveset([ Moves.TRICK_OR_TREAT ]); game.override.enemySpecies(Species.GASTLY); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); @@ -321,9 +320,9 @@ describe("Abilities - Protean", () => { test( "ability applies correctly and the pokemon curses itself", async () => { - game.override.moveset([Moves.CURSE]); + game.override.moveset([ Moves.CURSE ]); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; expect(leadPokemon).not.toBe(undefined); diff --git a/src/test/abilities/quick_draw.test.ts b/src/test/abilities/quick_draw.test.ts index dbed6c822c4..4979152f4d6 100644 --- a/src/test/abilities/quick_draw.test.ts +++ b/src/test/abilities/quick_draw.test.ts @@ -27,12 +27,12 @@ describe("Abilities - Quick Draw", () => { game.override.starterSpecies(Species.MAGIKARP); game.override.ability(Abilities.QUICK_DRAW); - game.override.moveset([Moves.TACKLE, Moves.TAIL_WHIP]); + game.override.moveset([ Moves.TACKLE, Moves.TAIL_WHIP ]); game.override.enemyLevel(100); game.override.enemySpecies(Species.MAGIKARP); game.override.enemyAbility(Abilities.BALL_FETCH); - game.override.enemyMoveset([Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE ]); vi.spyOn(allAbilities[Abilities.QUICK_DRAW].getAttrs(BypassSpeedChanceAbAttr)[0], "chance", "get").mockReturnValue(100); }); @@ -75,7 +75,7 @@ describe("Abilities - Quick Draw", () => { ); test("does not increase priority", async () => { - game.override.enemyMoveset([Moves.EXTREME_SPEED]); + game.override.enemyMoveset([ Moves.EXTREME_SPEED ]); await game.startBattle(); diff --git a/src/test/abilities/sand_spit.test.ts b/src/test/abilities/sand_spit.test.ts index add13ede296..1c21cff3c14 100644 --- a/src/test/abilities/sand_spit.test.ts +++ b/src/test/abilities/sand_spit.test.ts @@ -31,11 +31,11 @@ describe("Abilities - Sand Spit", () => { game.override.starterSpecies(Species.SILICOBRA); game.override.ability(Abilities.SAND_SPIT); - game.override.moveset([Moves.SPLASH, Moves.COIL]); + game.override.moveset([ Moves.SPLASH, Moves.COIL ]); }); it("should trigger when hit with damaging move", async () => { - game.override.enemyMoveset([Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE ]); await game.startBattle(); game.move.select(Moves.SPLASH); @@ -45,7 +45,7 @@ describe("Abilities - Sand Spit", () => { }, 20000); it("should not trigger when targetted with status moves", async () => { - game.override.enemyMoveset([Moves.GROWL]); + game.override.enemyMoveset([ Moves.GROWL ]); await game.startBattle(); game.move.select(Moves.COIL); diff --git a/src/test/abilities/sand_veil.test.ts b/src/test/abilities/sand_veil.test.ts index 201d8d89600..c62357f17af 100644 --- a/src/test/abilities/sand_veil.test.ts +++ b/src/test/abilities/sand_veil.test.ts @@ -12,7 +12,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; - describe("Abilities - Sand Veil", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -29,10 +28,10 @@ describe("Abilities - Sand Veil", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); game.override.enemySpecies(Species.MEOWSCARADA); game.override.enemyAbility(Abilities.INSOMNIA); - game.override.enemyMoveset([Moves.TWISTER, Moves.TWISTER, Moves.TWISTER, Moves.TWISTER]); + game.override.enemyMoveset([ Moves.TWISTER, Moves.TWISTER, Moves.TWISTER, Moves.TWISTER ]); game.override.startingLevel(100); game.override.enemyLevel(100); game.override @@ -43,7 +42,7 @@ describe("Abilities - Sand Veil", () => { test( "ability should increase the evasiveness of the source", async () => { - await game.startBattle([Species.SNORLAX, Species.BLISSEY]); + await game.startBattle([ Species.SNORLAX, Species.BLISSEY ]); const leadPokemon = game.scene.getPlayerField(); diff --git a/src/test/abilities/sap_sipper.test.ts b/src/test/abilities/sap_sipper.test.ts index b73bc3d9e27..a4ce0c1b8f6 100644 --- a/src/test/abilities/sap_sipper.test.ts +++ b/src/test/abilities/sap_sipper.test.ts @@ -148,8 +148,8 @@ describe("Abilities - Sap Sipper", () => { const moveToUse = Moves.METRONOME; const enemyAbility = Abilities.SAP_SIPPER; - game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + game.override.moveset([ moveToUse ]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE ]); game.override.enemySpecies(Species.RATTATA); game.override.enemyAbility(enemyAbility); diff --git a/src/test/abilities/schooling.test.ts b/src/test/abilities/schooling.test.ts index 4c5a66a41b7..aacc7bbd4c2 100644 --- a/src/test/abilities/schooling.test.ts +++ b/src/test/abilities/schooling.test.ts @@ -8,7 +8,6 @@ import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - describe("Abilities - SCHOOLING", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -28,8 +27,8 @@ describe("Abilities - SCHOOLING", () => { const moveToUse = Moves.SPLASH; game.override.battleType("single"); game.override.ability(Abilities.SCHOOLING); - game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.moveset([ moveToUse ]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); }); test( @@ -42,7 +41,7 @@ describe("Abilities - SCHOOLING", () => { [Species.WISHIWASHI]: schoolForm, }); - await game.startBattle([Species.MAGIKARP, Species.WISHIWASHI]); + await game.startBattle([ Species.MAGIKARP, Species.WISHIWASHI ]); const wishiwashi = game.scene.getParty().find((p) => p.species.speciesId === Species.WISHIWASHI)!; expect(wishiwashi).not.toBe(undefined); diff --git a/src/test/abilities/screen_cleaner.test.ts b/src/test/abilities/screen_cleaner.test.ts index 3c0d12a06ea..c036aa90a77 100644 --- a/src/test/abilities/screen_cleaner.test.ts +++ b/src/test/abilities/screen_cleaner.test.ts @@ -30,10 +30,10 @@ describe("Abilities - Screen Cleaner", () => { }); it("removes Aurora Veil", async () => { - game.override.moveset([Moves.HAIL]); - game.override.enemyMoveset([Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL]); + game.override.moveset([ Moves.HAIL ]); + game.override.enemyMoveset([ Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL ]); - await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP, Species.MAGIKARP ]); game.move.select(Moves.HAIL); await game.phaseInterceptor.to(TurnEndPhase); @@ -48,9 +48,9 @@ describe("Abilities - Screen Cleaner", () => { }); it("removes Light Screen", async () => { - game.override.enemyMoveset([Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN]); + game.override.enemyMoveset([ Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN ]); - await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP, Species.MAGIKARP ]); game.move.select(Moves.SPLASH); await game.phaseInterceptor.to(TurnEndPhase); @@ -65,9 +65,9 @@ describe("Abilities - Screen Cleaner", () => { }); it("removes Reflect", async () => { - game.override.enemyMoveset([Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT]); + game.override.enemyMoveset([ Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT ]); - await game.startBattle([Species.MAGIKARP, Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP, Species.MAGIKARP ]); game.move.select(Moves.SPLASH); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/abilities/serene_grace.test.ts b/src/test/abilities/serene_grace.test.ts index e06288b9de9..3155594c81d 100644 --- a/src/test/abilities/serene_grace.test.ts +++ b/src/test/abilities/serene_grace.test.ts @@ -27,12 +27,12 @@ describe("Abilities - Serene Grace", () => { beforeEach(() => { game = new GameManager(phaserGame); - const movesToUse = [Moves.AIR_SLASH, Moves.TACKLE]; + const movesToUse = [ Moves.AIR_SLASH, Moves.TACKLE ]; game.override.battleType("single"); game.override.enemySpecies(Species.ONIX); game.override.startingLevel(100); game.override.moveset(movesToUse); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); }); it("Move chance without Serene Grace", async () => { @@ -47,7 +47,7 @@ describe("Abilities - Serene Grace", () => { game.move.select(moveToUse); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); // Check chance of Air Slash without Serene Grace @@ -74,7 +74,7 @@ describe("Abilities - Serene Grace", () => { game.move.select(moveToUse); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); // Check chance of Air Slash with Serene Grace diff --git a/src/test/abilities/sheer_force.test.ts b/src/test/abilities/sheer_force.test.ts index 69b47e1eaae..a2600476d6d 100644 --- a/src/test/abilities/sheer_force.test.ts +++ b/src/test/abilities/sheer_force.test.ts @@ -9,6 +9,7 @@ import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { allMoves } from "#app/data/move"; describe("Abilities - Sheer Force", () => { @@ -27,12 +28,12 @@ describe("Abilities - Sheer Force", () => { beforeEach(() => { game = new GameManager(phaserGame); - const movesToUse = [Moves.AIR_SLASH, Moves.BIND, Moves.CRUSH_CLAW, Moves.TACKLE]; + const movesToUse = [ Moves.AIR_SLASH, Moves.BIND, Moves.CRUSH_CLAW, Moves.TACKLE ]; game.override.battleType("single"); game.override.enemySpecies(Species.ONIX); game.override.startingLevel(100); game.override.moveset(movesToUse); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); }); it("Sheer Force", async () => { @@ -48,7 +49,7 @@ describe("Abilities - Sheer Force", () => { game.move.select(moveToUse); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); const phase = game.scene.getCurrentPhase() as MoveEffectPhase; @@ -81,7 +82,7 @@ describe("Abilities - Sheer Force", () => { game.move.select(moveToUse); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); const phase = game.scene.getCurrentPhase() as MoveEffectPhase; @@ -114,7 +115,7 @@ describe("Abilities - Sheer Force", () => { game.move.select(moveToUse); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); const phase = game.scene.getCurrentPhase() as MoveEffectPhase; @@ -149,7 +150,7 @@ describe("Abilities - Sheer Force", () => { game.move.select(moveToUse); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); const phase = game.scene.getCurrentPhase() as MoveEffectPhase; @@ -174,5 +175,31 @@ describe("Abilities - Sheer Force", () => { }, 20000); + it("Two Pokemon with abilities disabled by Sheer Force hitting each other should not cause a crash", async () => { + const moveToUse = Moves.CRUNCH; + game.override.enemyAbility(Abilities.COLOR_CHANGE) + .ability(Abilities.COLOR_CHANGE) + .moveset(moveToUse) + .enemyMoveset(moveToUse); + + await game.classicMode.startBattle([ + Species.PIDGEOT + ]); + + const pidgeot = game.scene.getParty()[0]; + const onix = game.scene.getEnemyParty()[0]; + + pidgeot.stats[Stat.DEF] = 10000; + onix.stats[Stat.DEF] = 10000; + + game.move.select(moveToUse); + await game.toNextTurn(); + + // Check that both Pokemon's Color Change activated + const expectedTypes = [ allMoves[moveToUse].type ]; + expect(pidgeot.getTypes()).toStrictEqual(expectedTypes); + expect(onix.getTypes()).toStrictEqual(expectedTypes); + }); + //TODO King's Rock Interaction Unit Test }); diff --git a/src/test/abilities/shield_dust.test.ts b/src/test/abilities/shield_dust.test.ts index 8a0b769827d..0f831fcf3fa 100644 --- a/src/test/abilities/shield_dust.test.ts +++ b/src/test/abilities/shield_dust.test.ts @@ -27,13 +27,13 @@ describe("Abilities - Shield Dust", () => { beforeEach(() => { game = new GameManager(phaserGame); - const movesToUse = [Moves.AIR_SLASH]; + const movesToUse = [ Moves.AIR_SLASH ]; game.override.battleType("single"); game.override.enemySpecies(Species.ONIX); game.override.enemyAbility(Abilities.SHIELD_DUST); game.override.startingLevel(100); game.override.moveset(movesToUse); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); }); it("Shield Dust", async () => { @@ -48,7 +48,7 @@ describe("Abilities - Shield Dust", () => { game.move.select(moveToUse); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); // Shield Dust negates secondary effect diff --git a/src/test/abilities/shields_down.test.ts b/src/test/abilities/shields_down.test.ts index 411c23fc652..d3d72ac80a5 100644 --- a/src/test/abilities/shields_down.test.ts +++ b/src/test/abilities/shields_down.test.ts @@ -8,7 +8,6 @@ import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - describe("Abilities - SHIELDS DOWN", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -28,8 +27,8 @@ describe("Abilities - SHIELDS DOWN", () => { const moveToUse = Moves.SPLASH; game.override.battleType("single"); game.override.ability(Abilities.SHIELDS_DOWN); - game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.moveset([ moveToUse ]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); }); test( @@ -42,7 +41,7 @@ describe("Abilities - SHIELDS DOWN", () => { [Species.MINIOR]: coreForm, }); - await game.startBattle([Species.MAGIKARP, Species.MINIOR]); + await game.startBattle([ Species.MAGIKARP, Species.MINIOR ]); const minior = game.scene.getParty().find((p) => p.species.speciesId === Species.MINIOR)!; expect(minior).not.toBe(undefined); diff --git a/src/test/abilities/stall.test.ts b/src/test/abilities/stall.test.ts index 7baf7c846f0..b51c56dbe1f 100644 --- a/src/test/abilities/stall.test.ts +++ b/src/test/abilities/stall.test.ts @@ -26,8 +26,8 @@ describe("Abilities - Stall", () => { game.override.disableCrits(); game.override.enemySpecies(Species.REGIELEKI); game.override.enemyAbility(Abilities.STALL); - game.override.enemyMoveset([Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK]); - game.override.moveset([Moves.QUICK_ATTACK, Moves.TACKLE]); + game.override.enemyMoveset([ Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK, Moves.QUICK_ATTACK ]); + game.override.moveset([ Moves.QUICK_ATTACK, Moves.TACKLE ]); }); /** @@ -37,7 +37,7 @@ describe("Abilities - Stall", () => { **/ it("Pokemon with Stall should move last in its priority bracket regardless of speed", async () => { - await game.startBattle([Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE ]); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); @@ -50,12 +50,12 @@ describe("Abilities - Stall", () => { const commandOrder = phase.getCommandOrder(); // The player Pokemon (without Stall) goes first despite having lower speed than the opponent. // The opponent Pokemon (with Stall) goes last despite having higher speed than the player Pokemon. - expect(speedOrder).toEqual([enemyIndex, playerIndex]); - expect(commandOrder).toEqual([playerIndex, enemyIndex]); + expect(speedOrder).toEqual([ enemyIndex, playerIndex ]); + expect(commandOrder).toEqual([ playerIndex, enemyIndex ]); }, 20000); it("Pokemon with Stall will go first if a move that is in a higher priority bracket than the opponent's move is used", async () => { - await game.startBattle([Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE ]); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); @@ -68,13 +68,13 @@ describe("Abilities - Stall", () => { const commandOrder = phase.getCommandOrder(); // The opponent Pokemon (with Stall) goes first because its move is still within a higher priority bracket than its opponent. // The player Pokemon goes second because its move is in a lower priority bracket. - expect(speedOrder).toEqual([enemyIndex, playerIndex]); - expect(commandOrder).toEqual([enemyIndex, playerIndex]); + expect(speedOrder).toEqual([ enemyIndex, playerIndex ]); + expect(commandOrder).toEqual([ enemyIndex, playerIndex ]); }, 20000); it("If both Pokemon have stall and use the same move, speed is used to determine who goes first.", async () => { game.override.ability(Abilities.STALL); - await game.startBattle([Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE ]); const playerIndex = game.scene.getPlayerPokemon()!.getBattlerIndex(); const enemyIndex = game.scene.getEnemyPokemon()!.getBattlerIndex(); @@ -88,7 +88,7 @@ describe("Abilities - Stall", () => { // The opponent Pokemon (with Stall) goes first because it has a higher speed. // The player Pokemon (with Stall) goes second because its speed is lower. - expect(speedOrder).toEqual([enemyIndex, playerIndex]); - expect(commandOrder).toEqual([enemyIndex, playerIndex]); + expect(speedOrder).toEqual([ enemyIndex, playerIndex ]); + expect(commandOrder).toEqual([ enemyIndex, playerIndex ]); }, 20000); }); diff --git a/src/test/abilities/steely_spirit.test.ts b/src/test/abilities/steely_spirit.test.ts index 7b5879555be..61e76989060 100644 --- a/src/test/abilities/steely_spirit.test.ts +++ b/src/test/abilities/steely_spirit.test.ts @@ -29,13 +29,13 @@ describe("Abilities - Steely Spirit", () => { game.override.battleType("double"); game.override.enemySpecies(Species.SHUCKLE); game.override.enemyAbility(Abilities.BALL_FETCH); - game.override.moveset([Moves.IRON_HEAD, Moves.SPLASH]); + game.override.moveset([ Moves.IRON_HEAD, Moves.SPLASH ]); game.override.enemyMoveset(Moves.SPLASH); vi.spyOn(allMoves[moveToCheck], "calculateBattlePower"); }); it("increases Steel-type moves' power used by the user and its allies by 50%", async () => { - await game.classicMode.startBattle([Species.PIKACHU, Species.SHUCKLE]); + await game.classicMode.startBattle([ Species.PIKACHU, Species.SHUCKLE ]); const boostSource = game.scene.getPlayerField()[1]; const enemyToCheck = game.scene.getEnemyPokemon()!; @@ -51,7 +51,7 @@ describe("Abilities - Steely Spirit", () => { }); it("stacks if multiple users with this ability are on the field.", async () => { - await game.classicMode.startBattle([Species.PIKACHU, Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU, Species.PIKACHU ]); const enemyToCheck = game.scene.getEnemyPokemon()!; game.scene.getPlayerField().forEach(p => { @@ -68,7 +68,7 @@ describe("Abilities - Steely Spirit", () => { }); it("does not take effect when suppressed", async () => { - await game.classicMode.startBattle([Species.PIKACHU, Species.SHUCKLE]); + await game.classicMode.startBattle([ Species.PIKACHU, Species.SHUCKLE ]); const boostSource = game.scene.getPlayerField()[1]; const enemyToCheck = game.scene.getEnemyPokemon()!; @@ -90,12 +90,12 @@ describe("Abilities - Steely Spirit", () => { it("affects variable-type moves if their resolved type is Steel", async () => { game.override .ability(Abilities.STEELY_SPIRIT) - .moveset([Moves.REVELATION_DANCE]); + .moveset([ Moves.REVELATION_DANCE ]); const revelationDance = allMoves[Moves.REVELATION_DANCE]; vi.spyOn(revelationDance, "calculateBattlePower"); - await game.classicMode.startBattle([Species.KLINKLANG]); + await game.classicMode.startBattle([ Species.KLINKLANG ]); game.move.select(Moves.REVELATION_DANCE); diff --git a/src/test/abilities/sturdy.test.ts b/src/test/abilities/sturdy.test.ts index c329d0830d3..49384e69f83 100644 --- a/src/test/abilities/sturdy.test.ts +++ b/src/test/abilities/sturdy.test.ts @@ -9,7 +9,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - describe("Abilities - Sturdy", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -30,7 +29,7 @@ describe("Abilities - Sturdy", () => { game.override.starterSpecies(Species.LUCARIO); game.override.startingLevel(100); - game.override.moveset([Moves.CLOSE_COMBAT, Moves.FISSURE]); + game.override.moveset([ Moves.CLOSE_COMBAT, Moves.FISSURE ]); game.override.enemySpecies(Species.ARON); game.override.enemyLevel(5); diff --git a/src/test/abilities/sweet_veil.test.ts b/src/test/abilities/sweet_veil.test.ts index c2946443245..ef66cb1c68a 100644 --- a/src/test/abilities/sweet_veil.test.ts +++ b/src/test/abilities/sweet_veil.test.ts @@ -26,14 +26,14 @@ describe("Abilities - Sweet Veil", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("double"); - game.override.moveset([Moves.SPLASH, Moves.REST, Moves.YAWN]); + game.override.moveset([ Moves.SPLASH, Moves.REST, Moves.YAWN ]); game.override.enemySpecies(Species.MAGIKARP); game.override.enemyAbility(Abilities.BALL_FETCH); - game.override.enemyMoveset([Moves.POWDER, Moves.POWDER, Moves.POWDER, Moves.POWDER]); + game.override.enemyMoveset([ Moves.POWDER, Moves.POWDER, Moves.POWDER, Moves.POWDER ]); }); it("prevents the user and its allies from falling asleep", async () => { - await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]); + await game.startBattle([ Species.SWIRLIX, Species.MAGIKARP ]); game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH, 1); @@ -45,7 +45,7 @@ describe("Abilities - Sweet Veil", () => { it("causes Rest to fail when used by the user or its allies", async () => { game.override.enemyMoveset(Moves.SPLASH); - await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]); + await game.startBattle([ Species.SWIRLIX, Species.MAGIKARP ]); game.move.select(Moves.SPLASH); game.move.select(Moves.REST, 1); @@ -56,8 +56,8 @@ describe("Abilities - Sweet Veil", () => { }); it("causes Yawn to fail if used on the user or its allies", async () => { - game.override.enemyMoveset([Moves.YAWN, Moves.YAWN, Moves.YAWN, Moves.YAWN]); - await game.startBattle([Species.SWIRLIX, Species.MAGIKARP]); + game.override.enemyMoveset([ Moves.YAWN, Moves.YAWN, Moves.YAWN, Moves.YAWN ]); + await game.startBattle([ Species.SWIRLIX, Species.MAGIKARP ]); game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH, 1); @@ -73,7 +73,7 @@ describe("Abilities - Sweet Veil", () => { game.override.startingLevel(5); game.override.enemyMoveset(Moves.SPLASH); - await game.startBattle([Species.SHUCKLE, Species.SHUCKLE, Species.SWIRLIX]); + await game.startBattle([ Species.SHUCKLE, Species.SHUCKLE, Species.SWIRLIX ]); game.move.select(Moves.SPLASH); game.move.select(Moves.YAWN, 1, BattlerIndex.PLAYER); diff --git a/src/test/abilities/synchronize.test.ts b/src/test/abilities/synchronize.test.ts index 6e0aa46763f..cdd2834f588 100644 --- a/src/test/abilities/synchronize.test.ts +++ b/src/test/abilities/synchronize.test.ts @@ -28,12 +28,12 @@ describe("Abilities - Synchronize", () => { .startingLevel(100) .enemySpecies(Species.MAGIKARP) .enemyAbility(Abilities.SYNCHRONIZE) - .moveset([Moves.SPLASH, Moves.THUNDER_WAVE, Moves.SPORE, Moves.PSYCHO_SHIFT]) + .moveset([ Moves.SPLASH, Moves.THUNDER_WAVE, Moves.SPORE, Moves.PSYCHO_SHIFT ]) .ability(Abilities.NO_GUARD); }, 20000); it("does not trigger when no status is applied by opponent Pokemon", async () => { - await game.classicMode.startBattle([Species.FEEBAS]); + await game.classicMode.startBattle([ Species.FEEBAS ]); game.move.select(Moves.SPLASH); await game.phaseInterceptor.to("BerryPhase"); @@ -43,7 +43,7 @@ describe("Abilities - Synchronize", () => { }, 20000); it("sets the status of the source pokemon to Paralysis when paralyzed by it", async () => { - await game.classicMode.startBattle([Species.FEEBAS]); + await game.classicMode.startBattle([ Species.FEEBAS ]); game.move.select(Moves.THUNDER_WAVE); await game.phaseInterceptor.to("BerryPhase"); @@ -71,7 +71,7 @@ describe("Abilities - Synchronize", () => { .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Array(4).fill(Moves.TOXIC_SPIKES)); - await game.classicMode.startBattle([Species.FEEBAS, Species.MILOTIC]); + await game.classicMode.startBattle([ Species.FEEBAS, Species.MILOTIC ]); game.move.select(Moves.SPLASH); await game.toNextTurn(); @@ -85,7 +85,7 @@ describe("Abilities - Synchronize", () => { }, 20000); it("shows ability even if it fails to set the status of the opponent Pokemon", async () => { - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); game.move.select(Moves.THUNDER_WAVE); await game.phaseInterceptor.to("BerryPhase"); diff --git a/src/test/abilities/tera_shell.test.ts b/src/test/abilities/tera_shell.test.ts index 9995f7c34c3..01382d0fd9a 100644 --- a/src/test/abilities/tera_shell.test.ts +++ b/src/test/abilities/tera_shell.test.ts @@ -26,10 +26,10 @@ describe("Abilities - Tera Shell", () => { game.override .battleType("single") .ability(Abilities.TERA_SHELL) - .moveset([Moves.SPLASH]) + .moveset([ Moves.SPLASH ]) .enemySpecies(Species.SNORLAX) .enemyAbility(Abilities.INSOMNIA) - .enemyMoveset([Moves.MACH_PUNCH]) + .enemyMoveset([ Moves.MACH_PUNCH ]) .startingLevel(100) .enemyLevel(100); }); @@ -37,7 +37,7 @@ describe("Abilities - Tera Shell", () => { it( "should change the effectiveness of non-resisted attacks when the source is at full HP", async () => { - await game.classicMode.startBattle([Species.SNORLAX]); + await game.classicMode.startBattle([ Species.SNORLAX ]); const playerPokemon = game.scene.getPlayerPokemon()!; vi.spyOn(playerPokemon, "getMoveEffectiveness"); @@ -59,9 +59,9 @@ describe("Abilities - Tera Shell", () => { it( "should not override type immunities", async () => { - game.override.enemyMoveset([Moves.SHADOW_SNEAK]); + game.override.enemyMoveset([ Moves.SHADOW_SNEAK ]); - await game.classicMode.startBattle([Species.SNORLAX]); + await game.classicMode.startBattle([ Species.SNORLAX ]); const playerPokemon = game.scene.getPlayerPokemon()!; vi.spyOn(playerPokemon, "getMoveEffectiveness"); @@ -76,9 +76,9 @@ describe("Abilities - Tera Shell", () => { it( "should not override type multipliers less than 0.5x", async () => { - game.override.enemyMoveset([Moves.QUICK_ATTACK]); + game.override.enemyMoveset([ Moves.QUICK_ATTACK ]); - await game.classicMode.startBattle([Species.AGGRON]); + await game.classicMode.startBattle([ Species.AGGRON ]); const playerPokemon = game.scene.getPlayerPokemon()!; vi.spyOn(playerPokemon, "getMoveEffectiveness"); @@ -93,9 +93,9 @@ describe("Abilities - Tera Shell", () => { it( "should not affect the effectiveness of fixed-damage moves", async () => { - game.override.enemyMoveset([Moves.DRAGON_RAGE]); + game.override.enemyMoveset([ Moves.DRAGON_RAGE ]); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerPokemon()!; vi.spyOn(playerPokemon, "apply"); @@ -111,16 +111,16 @@ describe("Abilities - Tera Shell", () => { it( "should change the effectiveness of all strikes of a multi-strike move", async () => { - game.override.enemyMoveset([Moves.DOUBLE_HIT]); + game.override.enemyMoveset([ Moves.DOUBLE_HIT ]); - await game.classicMode.startBattle([Species.SNORLAX]); + await game.classicMode.startBattle([ Species.SNORLAX ]); const playerPokemon = game.scene.getPlayerPokemon()!; vi.spyOn(playerPokemon, "apply"); game.move.select(Moves.SPLASH); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.move.forceHit(); for (let i = 0; i < 2; i++) { await game.phaseInterceptor.to("MoveEffectPhase"); diff --git a/src/test/abilities/unseen_fist.test.ts b/src/test/abilities/unseen_fist.test.ts index 0f285abd98f..f8fa8a723fe 100644 --- a/src/test/abilities/unseen_fist.test.ts +++ b/src/test/abilities/unseen_fist.test.ts @@ -9,7 +9,6 @@ import { BattlerTagType } from "#app/enums/battler-tag-type"; import { BerryPhase } from "#app/phases/berry-phase"; - describe("Abilities - Unseen Fist", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -29,7 +28,7 @@ describe("Abilities - Unseen Fist", () => { game.override.battleType("single"); game.override.starterSpecies(Species.URSHIFU); game.override.enemySpecies(Species.SNORLAX); - game.override.enemyMoveset([Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT]); + game.override.enemyMoveset([ Moves.PROTECT, Moves.PROTECT, Moves.PROTECT, Moves.PROTECT ]); game.override.startingLevel(100); game.override.enemyLevel(100); }); @@ -66,7 +65,7 @@ describe("Abilities - Unseen Fist", () => { "should cause a contact move to ignore Protect, but not Substitute", async () => { game.override.enemyLevel(1); - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); await game.startBattle(); @@ -84,8 +83,8 @@ describe("Abilities - Unseen Fist", () => { }); async function testUnseenFistHitResult(game: GameManager, attackMove: Moves, protectMove: Moves, shouldSucceed: boolean = true): Promise { - game.override.moveset([attackMove]); - game.override.enemyMoveset([protectMove, protectMove, protectMove, protectMove]); + game.override.moveset([ attackMove ]); + game.override.enemyMoveset([ protectMove, protectMove, protectMove, protectMove ]); await game.startBattle(); diff --git a/src/test/abilities/volt_absorb.test.ts b/src/test/abilities/volt_absorb.test.ts index 9bd5de7df57..ec82b00ec5a 100644 --- a/src/test/abilities/volt_absorb.test.ts +++ b/src/test/abilities/volt_absorb.test.ts @@ -34,9 +34,9 @@ describe("Abilities - Volt Absorb", () => { const moveToUse = Moves.CHARGE; const ability = Abilities.VOLT_ABSORB; - game.override.moveset([moveToUse]); + game.override.moveset([ moveToUse ]); game.override.ability(ability); - game.override.enemyMoveset([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE ]); game.override.enemySpecies(Species.DUSKULL); game.override.enemyAbility(Abilities.BALL_FETCH); @@ -64,11 +64,30 @@ describe("Abilities - Volt Absorb", () => { game.move.select(Moves.THUNDERBOLT); enemyPokemon.hp = enemyPokemon.hp - 1; - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("MoveEffectPhase"); await game.move.forceMiss(); await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); }); + it("regardless of accuracy should not trigger on pokemon in semi invulnerable state", async () => { + game.override.moveset(Moves.THUNDERBOLT); + game.override.enemyMoveset(Moves.DIVE); + game.override.enemySpecies(Species.MAGIKARP); + game.override.enemyAbility(Abilities.VOLT_ABSORB); + + await game.classicMode.startBattle(); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.THUNDERBOLT); + enemyPokemon.hp = enemyPokemon.hp - 1; + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.phaseInterceptor.to("MoveEffectPhase"); + + await game.move.forceMiss(); + await game.phaseInterceptor.to("BerryPhase", false); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); + }); }); diff --git a/src/test/abilities/wind_power.test.ts b/src/test/abilities/wind_power.test.ts index 12b8d2f2299..538b65f898b 100644 --- a/src/test/abilities/wind_power.test.ts +++ b/src/test/abilities/wind_power.test.ts @@ -26,12 +26,12 @@ describe("Abilities - Wind Power", () => { game.override.battleType("single"); game.override.enemySpecies(Species.SHIFTRY); game.override.enemyAbility(Abilities.WIND_POWER); - game.override.moveset([Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM]); + game.override.moveset([ Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM ]); game.override.enemyMoveset(Moves.SPLASH); }); it("it becomes charged when hit by wind moves", async () => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const shiftry = game.scene.getEnemyPokemon()!; expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeUndefined(); @@ -46,7 +46,7 @@ describe("Abilities - Wind Power", () => { game.override.ability(Abilities.WIND_POWER); game.override.enemySpecies(Species.MAGIKARP); - await game.startBattle([Species.SHIFTRY]); + await game.startBattle([ Species.SHIFTRY ]); const shiftry = game.scene.getPlayerPokemon()!; expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeUndefined(); @@ -61,7 +61,7 @@ describe("Abilities - Wind Power", () => { game.override.enemySpecies(Species.MAGIKARP); game.override.ability(Abilities.WIND_POWER); - await game.startBattle([Species.SHIFTRY]); + await game.startBattle([ Species.SHIFTRY ]); const magikarp = game.scene.getEnemyPokemon()!; const shiftry = game.scene.getPlayerPokemon()!; @@ -79,7 +79,7 @@ describe("Abilities - Wind Power", () => { it("does not interact with Sandstorm", async () => { game.override.enemySpecies(Species.MAGIKARP); - await game.startBattle([Species.SHIFTRY]); + await game.startBattle([ Species.SHIFTRY ]); const shiftry = game.scene.getPlayerPokemon()!; expect(shiftry.getTag(BattlerTagType.CHARGED)).toBeUndefined(); diff --git a/src/test/abilities/wind_rider.test.ts b/src/test/abilities/wind_rider.test.ts index c917f56e101..cd7094fb0a9 100644 --- a/src/test/abilities/wind_rider.test.ts +++ b/src/test/abilities/wind_rider.test.ts @@ -26,7 +26,7 @@ describe("Abilities - Wind Rider", () => { .battleType("single") .enemySpecies(Species.SHIFTRY) .enemyAbility(Abilities.WIND_RIDER) - .moveset([Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM]) + .moveset([ Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM ]) .enemyMoveset(Moves.SPLASH); }); @@ -49,7 +49,7 @@ describe("Abilities - Wind Rider", () => { .enemySpecies(Species.MAGIKARP) .ability(Abilities.WIND_RIDER); - await game.classicMode.startBattle([Species.SHIFTRY]); + await game.classicMode.startBattle([ Species.SHIFTRY ]); const shiftry = game.scene.getPlayerPokemon()!; expect(shiftry.getStatStage(Stat.ATK)).toBe(0); @@ -66,7 +66,7 @@ describe("Abilities - Wind Rider", () => { .enemySpecies(Species.MAGIKARP) .ability(Abilities.WIND_RIDER); - await game.classicMode.startBattle([Species.SHIFTRY]); + await game.classicMode.startBattle([ Species.SHIFTRY ]); const magikarp = game.scene.getEnemyPokemon()!; const shiftry = game.scene.getPlayerPokemon()!; @@ -86,7 +86,7 @@ describe("Abilities - Wind Rider", () => { .enemySpecies(Species.MAGIKARP) .ability(Abilities.WIND_RIDER); - await game.classicMode.startBattle([Species.SHIFTRY]); + await game.classicMode.startBattle([ Species.SHIFTRY ]); const magikarp = game.scene.getEnemyPokemon()!; const shiftry = game.scene.getPlayerPokemon()!; @@ -104,7 +104,7 @@ describe("Abilities - Wind Rider", () => { it("does not interact with Sandstorm", async () => { game.override.enemySpecies(Species.MAGIKARP); - await game.classicMode.startBattle([Species.SHIFTRY]); + await game.classicMode.startBattle([ Species.SHIFTRY ]); const shiftry = game.scene.getPlayerPokemon()!; expect(shiftry.getStatStage(Stat.ATK)).toBe(0); diff --git a/src/test/abilities/wonder_skin.test.ts b/src/test/abilities/wonder_skin.test.ts index 6ef985fbd42..6b25701e36a 100644 --- a/src/test/abilities/wonder_skin.test.ts +++ b/src/test/abilities/wonder_skin.test.ts @@ -25,7 +25,7 @@ describe("Abilities - Wonder Skin", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("single"); - game.override.moveset([Moves.TACKLE, Moves.CHARM]); + game.override.moveset([ Moves.TACKLE, Moves.CHARM ]); game.override.ability(Abilities.BALL_FETCH); game.override.enemySpecies(Species.SHUCKLE); game.override.enemyAbility(Abilities.WONDER_SKIN); @@ -37,7 +37,7 @@ describe("Abilities - Wonder Skin", () => { vi.spyOn(moveToCheck, "calculateBattleAccuracy"); - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); game.move.select(Moves.CHARM); await game.phaseInterceptor.to(MoveEffectPhase); @@ -49,14 +49,14 @@ describe("Abilities - Wonder Skin", () => { vi.spyOn(moveToCheck, "calculateBattleAccuracy"); - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); game.move.select(Moves.TACKLE); await game.phaseInterceptor.to(MoveEffectPhase); expect(moveToCheck.calculateBattleAccuracy).toHaveReturnedWith(100); }); - const bypassAbilities = [Abilities.MOLD_BREAKER, Abilities.TERAVOLT, Abilities.TURBOBLAZE]; + const bypassAbilities = [ Abilities.MOLD_BREAKER, Abilities.TERAVOLT, Abilities.TURBOBLAZE ]; bypassAbilities.forEach(ability => { it(`does not affect pokemon with ${allAbilities[ability].name}`, async () => { @@ -65,7 +65,7 @@ describe("Abilities - Wonder Skin", () => { game.override.ability(ability); vi.spyOn(moveToCheck, "calculateBattleAccuracy"); - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); game.move.select(Moves.CHARM); await game.phaseInterceptor.to(MoveEffectPhase); diff --git a/src/test/abilities/zen_mode.test.ts b/src/test/abilities/zen_mode.test.ts index b4c60aa7a7f..2601954a9a4 100644 --- a/src/test/abilities/zen_mode.test.ts +++ b/src/test/abilities/zen_mode.test.ts @@ -21,7 +21,6 @@ import { Status, StatusEffect } from "#app/data/status-effect"; import { SwitchType } from "#enums/switch-type"; - describe("Abilities - ZEN MODE", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -44,22 +43,22 @@ describe("Abilities - ZEN MODE", () => { game.override.enemyAbility(Abilities.HYDRATION); game.override.ability(Abilities.ZEN_MODE); game.override.startingLevel(100); - game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.moveset([ moveToUse ]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); }); test( "not enough damage to change form", async () => { const moveToUse = Moves.SPLASH; - await game.startBattle([Species.DARMANITAN]); + await game.startBattle([ Species.DARMANITAN ]); game.scene.getParty()[0].stats[Stat.HP] = 100; game.scene.getParty()[0].hp = 100; expect(game.scene.getParty()[0].formIndex).toBe(0); game.move.select(moveToUse); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to(DamagePhase, false); // await game.phaseInterceptor.runFrom(DamagePhase).to(DamagePhase, false); const damagePhase = game.scene.getCurrentPhase() as DamagePhase; @@ -74,14 +73,14 @@ describe("Abilities - ZEN MODE", () => { "enough damage to change form", async () => { const moveToUse = Moves.SPLASH; - await game.startBattle([Species.DARMANITAN]); + await game.startBattle([ Species.DARMANITAN ]); game.scene.getParty()[0].stats[Stat.HP] = 1000; game.scene.getParty()[0].hp = 100; expect(game.scene.getParty()[0].formIndex).toBe(0); game.move.select(moveToUse); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to(QuietFormChangePhase); await game.phaseInterceptor.to(TurnInitPhase, false); expect(game.scene.getParty()[0].hp).not.toBe(100); @@ -93,14 +92,14 @@ describe("Abilities - ZEN MODE", () => { "kill pokemon while on zen mode", async () => { const moveToUse = Moves.SPLASH; - await game.startBattle([Species.DARMANITAN, Species.CHARIZARD]); + await game.startBattle([ Species.DARMANITAN, Species.CHARIZARD ]); game.scene.getParty()[0].stats[Stat.HP] = 1000; game.scene.getParty()[0].hp = 100; expect(game.scene.getParty()[0].formIndex).toBe(0); game.move.select(moveToUse); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to(DamagePhase, false); // await game.phaseInterceptor.runFrom(DamagePhase).to(DamagePhase, false); const damagePhase = game.scene.getCurrentPhase() as DamagePhase; @@ -136,7 +135,7 @@ describe("Abilities - ZEN MODE", () => { [Species.DARMANITAN]: zenForm, }); - await game.startBattle([Species.MAGIKARP, Species.DARMANITAN]); + await game.startBattle([ Species.MAGIKARP, Species.DARMANITAN ]); const darmanitan = game.scene.getParty().find((p) => p.species.speciesId === Species.DARMANITAN)!; expect(darmanitan).not.toBe(undefined); diff --git a/src/test/abilities/zero_to_hero.test.ts b/src/test/abilities/zero_to_hero.test.ts index a7f7c970218..48a451e99a2 100644 --- a/src/test/abilities/zero_to_hero.test.ts +++ b/src/test/abilities/zero_to_hero.test.ts @@ -8,7 +8,6 @@ import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Abilities - ZERO TO HERO", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -40,7 +39,7 @@ describe("Abilities - ZERO TO HERO", () => { [Species.PALAFIN]: heroForm, }); - await game.startBattle([Species.FEEBAS, Species.PALAFIN, Species.PALAFIN]); + await game.startBattle([ Species.FEEBAS, Species.PALAFIN, Species.PALAFIN ]); const palafin1 = game.scene.getParty()[1]; const palafin2 = game.scene.getParty()[2]; @@ -62,7 +61,7 @@ describe("Abilities - ZERO TO HERO", () => { }); it("should swap to Hero form when switching out during a battle", async () => { - await game.startBattle([Species.PALAFIN, Species.FEEBAS]); + await game.startBattle([ Species.PALAFIN, Species.FEEBAS ]); const palafin = game.scene.getPlayerPokemon()!; expect(palafin.formIndex).toBe(baseForm); @@ -73,7 +72,7 @@ describe("Abilities - ZERO TO HERO", () => { }); it("should not swap to Hero form if switching due to faint", async () => { - await game.startBattle([Species.PALAFIN, Species.FEEBAS]); + await game.startBattle([ Species.PALAFIN, Species.FEEBAS ]); const palafin = game.scene.getPlayerPokemon()!; expect(palafin.formIndex).toBe(baseForm); @@ -90,7 +89,7 @@ describe("Abilities - ZERO TO HERO", () => { [Species.PALAFIN]: heroForm, }); - await game.startBattle([Species.PALAFIN, Species.FEEBAS]); + await game.startBattle([ Species.PALAFIN, Species.FEEBAS ]); const palafin = game.scene.getPlayerPokemon()!; expect(palafin.formIndex).toBe(heroForm); diff --git a/src/test/account.test.ts b/src/test/account.test.ts index eb6002f3cf2..8c36f2cd953 100644 --- a/src/test/account.test.ts +++ b/src/test/account.test.ts @@ -17,7 +17,7 @@ describe("account", () => { it("should set loggedInUser! to Guest if bypassLogin is true", async () => { vi.spyOn(battleScene, "bypassLogin", "get").mockReturnValue(true); - const [success, status] = await updateUserInfo(); + const [ success, status ] = await updateUserInfo(); expect(success).toBe(true); expect(status).toBe(200); @@ -39,7 +39,7 @@ describe("account", () => { ) ); - const [success, status] = await updateUserInfo(); + const [ success, status ] = await updateUserInfo(); expect(success).toBe(true); expect(status).toBe(200); @@ -53,7 +53,7 @@ describe("account", () => { new Response(null, { status: 401 }) ); - const [success, status] = await updateUserInfo(); + const [ success, status ] = await updateUserInfo(); expect(success).toBe(false); expect(status).toBe(401); @@ -64,7 +64,7 @@ describe("account", () => { vi.spyOn(battleScene, "bypassLogin", "get").mockReturnValue(false); vi.spyOn(utils, "apiFetch").mockRejectedValue(new Error("Api failed!")); - const [success, status] = await updateUserInfo(); + const [ success, status ] = await updateUserInfo(); expect(success).toBe(false); expect(status).toBe(500); diff --git a/src/test/achievements/achievement.test.ts b/src/test/achievements/achievement.test.ts index 24d00a3e77b..a3669c60463 100644 --- a/src/test/achievements/achievement.test.ts +++ b/src/test/achievements/achievement.test.ts @@ -61,8 +61,8 @@ describe("Achv", () => { const conditionFunc = vi.fn((scene: BattleScene, args: any[]) => args[0] === 10); const achv = new Achv("", "Test Achievement", "Test Description", "test_icon", 10, conditionFunc); - expect(achv.validate(new BattleScene(), [5])).toBe(false); - expect(achv.validate(new BattleScene(), [10])).toBe(true); + expect(achv.validate(new BattleScene(), [ 5 ])).toBe(false); + expect(achv.validate(new BattleScene(), [ 10 ])).toBe(true); expect(conditionFunc).toHaveBeenCalledTimes(2); }); }); @@ -141,10 +141,10 @@ describe("DamageAchv", () => { const scene = new BattleScene(); const numberHolder = new NumberHolder(200); - expect(damageAchv.validate(scene, [numberHolder])).toBe(false); + expect(damageAchv.validate(scene, [ numberHolder ])).toBe(false); numberHolder.value = 300; - expect(damageAchv.validate(scene, [numberHolder])).toBe(true); + expect(damageAchv.validate(scene, [ numberHolder ])).toBe(true); }); }); @@ -160,10 +160,10 @@ describe("HealAchv", () => { const scene = new BattleScene(); const numberHolder = new NumberHolder(200); - expect(healAchv.validate(scene, [numberHolder])).toBe(false); + expect(healAchv.validate(scene, [ numberHolder ])).toBe(false); numberHolder.value = 300; - expect(healAchv.validate(scene, [numberHolder])).toBe(true); + expect(healAchv.validate(scene, [ numberHolder ])).toBe(true); }); }); @@ -179,10 +179,10 @@ describe("LevelAchv", () => { const scene = new BattleScene(); const integerHolder = new IntegerHolder(50); - expect(levelAchv.validate(scene, [integerHolder])).toBe(false); + expect(levelAchv.validate(scene, [ integerHolder ])).toBe(false); integerHolder.value = 150; - expect(levelAchv.validate(scene, [integerHolder])).toBe(true); + expect(levelAchv.validate(scene, [ integerHolder ])).toBe(true); }); }); @@ -198,7 +198,7 @@ describe("ModifierAchv", () => { const scene = new BattleScene(); const modifier = new TurnHeldItemTransferModifier(null!, 3, 1); - expect(modifierAchv.validate(scene, [modifier])).toBe(true); + expect(modifierAchv.validate(scene, [ modifier ])).toBe(true); }); }); diff --git a/src/test/arena/arena_gravity.test.ts b/src/test/arena/arena_gravity.test.ts index 47b8bf4cf70..b6982896571 100644 --- a/src/test/arena/arena_gravity.test.ts +++ b/src/test/arena/arena_gravity.test.ts @@ -27,7 +27,7 @@ describe("Arena - Gravity", () => { game = new GameManager(phaserGame); game.override .battleType("single") - .moveset([Moves.TACKLE, Moves.GRAVITY, Moves.FISSURE]) + .moveset([ Moves.TACKLE, Moves.GRAVITY, Moves.FISSURE ]) .ability(Abilities.UNNERVE) .enemyAbility(Abilities.BALL_FETCH) .enemySpecies(Species.SHUCKLE) @@ -42,7 +42,7 @@ describe("Arena - Gravity", () => { vi.spyOn(moveToCheck, "calculateBattleAccuracy"); // Setup Gravity on first turn - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); game.move.select(Moves.GRAVITY); await game.phaseInterceptor.to(TurnEndPhase); @@ -66,7 +66,7 @@ describe("Arena - Gravity", () => { vi.spyOn(moveToCheck, "calculateBattleAccuracy"); // Setup Gravity on first turn - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); game.move.select(Moves.GRAVITY); await game.phaseInterceptor.to(TurnEndPhase); @@ -86,9 +86,9 @@ describe("Arena - Gravity", () => { .startingLevel(5) .enemyLevel(5) .enemySpecies(Species.PIDGEOT) - .moveset([Moves.GRAVITY, Moves.EARTHQUAKE]); + .moveset([ Moves.GRAVITY, Moves.EARTHQUAKE ]); - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); const pidgeot = game.scene.getEnemyPokemon()!; vi.spyOn(pidgeot, "getAttackTypeEffectiveness"); @@ -119,9 +119,9 @@ describe("Arena - Gravity", () => { .startingLevel(5) .enemyLevel(5) .enemySpecies(Species.PIDGEOT) - .moveset([Moves.GRAVITY, Moves.THUNDERBOLT]); + .moveset([ Moves.GRAVITY, Moves.THUNDERBOLT ]); - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); const pidgeot = game.scene.getEnemyPokemon()!; vi.spyOn(pidgeot, "getAttackTypeEffectiveness"); diff --git a/src/test/arena/grassy_terrain.test.ts b/src/test/arena/grassy_terrain.test.ts index 01bbc778ded..ead4467925b 100644 --- a/src/test/arena/grassy_terrain.test.ts +++ b/src/test/arena/grassy_terrain.test.ts @@ -28,12 +28,12 @@ describe("Arena - Grassy Terrain", () => { .enemySpecies(Species.SHUCKLE) .enemyAbility(Abilities.STURDY) .enemyMoveset(Moves.FLY) - .moveset([Moves.GRASSY_TERRAIN, Moves.EARTHQUAKE]) + .moveset([ Moves.GRASSY_TERRAIN, Moves.EARTHQUAKE ]) .ability(Abilities.NO_GUARD); }); it("halves the damage of Earthquake", async () => { - await game.classicMode.startBattle([Species.TAUROS]); + await game.classicMode.startBattle([ Species.TAUROS ]); const eq = allMoves[Moves.EARTHQUAKE]; vi.spyOn(eq, "calculateBattlePower"); @@ -53,7 +53,7 @@ describe("Arena - Grassy Terrain", () => { }); it("Does not halve the damage of Earthquake if opponent is not grounded", async () => { - await game.classicMode.startBattle([Species.NINJASK]); + await game.classicMode.startBattle([ Species.NINJASK ]); const eq = allMoves[Moves.EARTHQUAKE]; vi.spyOn(eq, "calculateBattlePower"); diff --git a/src/test/arena/weather_fog.test.ts b/src/test/arena/weather_fog.test.ts index b47145e8dd0..db591dda2b8 100644 --- a/src/test/arena/weather_fog.test.ts +++ b/src/test/arena/weather_fog.test.ts @@ -27,11 +27,11 @@ describe("Weather - Fog", () => { game.override .weather(WeatherType.FOG) .battleType("single"); - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.ability(Abilities.BALL_FETCH); game.override.enemyAbility(Abilities.BALL_FETCH); game.override.enemySpecies(Species.MAGIKARP); - game.override.enemyMoveset([Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH ]); }); it("move accuracy is multiplied by 90%", async () => { @@ -39,7 +39,7 @@ describe("Weather - Fog", () => { vi.spyOn(moveToCheck, "calculateBattleAccuracy"); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.TACKLE); await game.phaseInterceptor.to(MoveEffectPhase); diff --git a/src/test/arena/weather_hail.test.ts b/src/test/arena/weather_hail.test.ts index 2070e40dbcc..b8f4276a3d9 100644 --- a/src/test/arena/weather_hail.test.ts +++ b/src/test/arena/weather_hail.test.ts @@ -31,10 +31,10 @@ describe("Weather - Hail", () => { }); it("inflicts damage equal to 1/16 of Pokemon's max HP at turn end", async () => { - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.SPLASH); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase"); @@ -44,11 +44,11 @@ describe("Weather - Hail", () => { }); it("does not inflict damage to a Pokemon that is underwater (Dive) or underground (Dig)", async () => { - game.override.moveset([Moves.DIG]); - await game.classicMode.startBattle([Species.MAGIKARP]); + game.override.moveset([ Moves.DIG ]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.DIG); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase"); @@ -60,7 +60,7 @@ describe("Weather - Hail", () => { }); it("does not inflict damage to Ice type Pokemon", async () => { - await game.classicMode.startBattle([Species.CLOYSTER]); + await game.classicMode.startBattle([ Species.CLOYSTER ]); game.move.select(Moves.SPLASH); diff --git a/src/test/arena/weather_sandstorm.test.ts b/src/test/arena/weather_sandstorm.test.ts index 2419ca11b70..09d0c1d2b77 100644 --- a/src/test/arena/weather_sandstorm.test.ts +++ b/src/test/arena/weather_sandstorm.test.ts @@ -32,7 +32,7 @@ describe("Weather - Sandstorm", () => { }); it("inflicts damage equal to 1/16 of Pokemon's max HP at turn end", async () => { - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.SPLASH); @@ -44,8 +44,8 @@ describe("Weather - Sandstorm", () => { }); it("does not inflict damage to a Pokemon that is underwater (Dive) or underground (Dig)", async () => { - game.override.moveset([Moves.DIVE]); - await game.classicMode.startBattle([Species.MAGIKARP]); + game.override.moveset([ Moves.DIVE ]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.DIVE); @@ -65,7 +65,7 @@ describe("Weather - Sandstorm", () => { .ability(Abilities.BALL_FETCH) .enemyAbility(Abilities.BALL_FETCH); - await game.classicMode.startBattle([Species.ROCKRUFF, Species.KLINK]); + await game.classicMode.startBattle([ Species.ROCKRUFF, Species.KLINK ]); game.move.select(Moves.SPLASH, 0); game.move.select(Moves.SPLASH, 1); @@ -78,7 +78,7 @@ describe("Weather - Sandstorm", () => { }); it("increases Rock type Pokemon Sp.Def by 50%", async () => { - await game.classicMode.startBattle([Species.ROCKRUFF]); + await game.classicMode.startBattle([ Species.ROCKRUFF ]); const playerPokemon = game.scene.getPlayerPokemon()!; const playerSpdef = playerPokemon.getStat(Stat.SPDEF); diff --git a/src/test/arena/weather_strong_winds.test.ts b/src/test/arena/weather_strong_winds.test.ts index 5ce0e61e647..557de93d644 100644 --- a/src/test/arena/weather_strong_winds.test.ts +++ b/src/test/arena/weather_strong_winds.test.ts @@ -28,13 +28,13 @@ describe("Weather - Strong Winds", () => { game.override.startingLevel(10); game.override.enemySpecies(Species.TAILLOW); game.override.enemyAbility(Abilities.DELTA_STREAM); - game.override.moveset([Moves.THUNDERBOLT, Moves.ICE_BEAM, Moves.ROCK_SLIDE]); + game.override.moveset([ Moves.THUNDERBOLT, Moves.ICE_BEAM, Moves.ROCK_SLIDE ]); }); it("electric type move is not very effective on Rayquaza", async () => { game.override.enemySpecies(Species.RAYQUAZA); - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const pikachu = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; @@ -45,7 +45,7 @@ describe("Weather - Strong Winds", () => { }); it("electric type move is neutral for flying type pokemon", async () => { - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const pikachu = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; @@ -56,7 +56,7 @@ describe("Weather - Strong Winds", () => { }); it("ice type move is neutral for flying type pokemon", async () => { - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const pikachu = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; @@ -67,7 +67,7 @@ describe("Weather - Strong Winds", () => { }); it("rock type move is neutral for flying type pokemon", async () => { - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const pikachu = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; @@ -80,7 +80,7 @@ describe("Weather - Strong Winds", () => { it("weather goes away when last trainer pokemon dies to indirect damage", async () => { game.override.enemyStatusEffect(StatusEffect.POISON); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const enemy = game.scene.getEnemyPokemon()!; enemy.hp = 1; diff --git a/src/test/battle/battle-order.test.ts b/src/test/battle/battle-order.test.ts index e19168962dc..d4e9950dec9 100644 --- a/src/test/battle/battle-order.test.ts +++ b/src/test/battle/battle-order.test.ts @@ -28,7 +28,7 @@ describe("Battle order", () => { game.override.enemySpecies(Species.MEWTWO); game.override.enemyAbility(Abilities.INSOMNIA); game.override.ability(Abilities.INSOMNIA); - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); }); it("opponent faster than player 50 vs 150", async () => { @@ -38,8 +38,8 @@ describe("Battle order", () => { const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; - vi.spyOn(playerPokemon, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 50]); // set playerPokemon's speed to 50 - vi.spyOn(enemyPokemon, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set enemyPokemon's speed to 150 + vi.spyOn(playerPokemon, "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 50 ]); // set playerPokemon's speed to 50 + vi.spyOn(enemyPokemon, "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 150 ]); // set enemyPokemon's speed to 150 game.move.select(Moves.TACKLE); await game.phaseInterceptor.run(EnemyCommandPhase); @@ -59,8 +59,8 @@ describe("Battle order", () => { const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; - vi.spyOn(playerPokemon, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set playerPokemon's speed to 150 - vi.spyOn(enemyPokemon, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 50]); // set enemyPokemon's speed to 50 + vi.spyOn(playerPokemon, "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 150 ]); // set playerPokemon's speed to 150 + vi.spyOn(enemyPokemon, "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 50 ]); // set enemyPokemon's speed to 50 game.move.select(Moves.TACKLE); await game.phaseInterceptor.run(EnemyCommandPhase); @@ -83,8 +83,8 @@ describe("Battle order", () => { const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); - playerPokemon.forEach(p => vi.spyOn(p, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 50])); // set both playerPokemons' speed to 50 - enemyPokemon.forEach(p => vi.spyOn(p, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150])); // set both enemyPokemons' speed to 150 + playerPokemon.forEach(p => vi.spyOn(p, "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 50 ])); // set both playerPokemons' speed to 50 + enemyPokemon.forEach(p => vi.spyOn(p, "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 150 ])); // set both enemyPokemons' speed to 150 const playerIndices = playerPokemon.map(p => p?.getBattlerIndex()); const enemyIndices = enemyPokemon.map(p => p?.getBattlerIndex()); @@ -109,9 +109,9 @@ describe("Battle order", () => { const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); - playerPokemon.forEach(p => vi.spyOn(p, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 100])); //set both playerPokemons' speed to 100 - vi.spyOn(enemyPokemon[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 100]); // set enemyPokemon's speed to 100 - vi.spyOn(enemyPokemon[1], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set enemyPokemon's speed to 150 + playerPokemon.forEach(p => vi.spyOn(p, "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 100 ])); //set both playerPokemons' speed to 100 + vi.spyOn(enemyPokemon[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 100 ]); // set enemyPokemon's speed to 100 + vi.spyOn(enemyPokemon[1], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 150 ]); // set enemyPokemon's speed to 150 const playerIndices = playerPokemon.map(p => p?.getBattlerIndex()); const enemyIndices = enemyPokemon.map(p => p?.getBattlerIndex()); @@ -136,10 +136,10 @@ describe("Battle order", () => { const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); - vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 100]); // set one playerPokemon's speed to 100 - vi.spyOn(playerPokemon[1], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set other playerPokemon's speed to 150 - vi.spyOn(enemyPokemon[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 100]); // set one enemyPokemon's speed to 100 - vi.spyOn(enemyPokemon[1], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set other enemyPokemon's speed to 150 + vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 100 ]); // set one playerPokemon's speed to 100 + vi.spyOn(playerPokemon[1], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 150 ]); // set other playerPokemon's speed to 150 + vi.spyOn(enemyPokemon[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 100 ]); // set one enemyPokemon's speed to 100 + vi.spyOn(enemyPokemon[1], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, 150 ]); // set other enemyPokemon's speed to 150 const playerIndices = playerPokemon.map(p => p?.getBattlerIndex()); const enemyIndices = enemyPokemon.map(p => p?.getBattlerIndex()); diff --git a/src/test/battle/battle.test.ts b/src/test/battle/battle.test.ts index 554692374d2..eed76397f85 100644 --- a/src/test/battle/battle.test.ts +++ b/src/test/battle/battle.test.ts @@ -99,9 +99,9 @@ describe("Test Battle Phase", () => { game.override .startingWave(3) .battleType("single"); - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.enemyAbility(Abilities.HYDRATION); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); await game.startBattle(); game.move.select(Moves.TACKLE); await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(SelectModifierPhase, false); @@ -112,9 +112,9 @@ describe("Test Battle Phase", () => { game.override.enemySpecies(Species.RATTATA); game.override.startingLevel(5); game.override.startingWave(3); - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.enemyAbility(Abilities.HYDRATION); - game.override.enemyMoveset([Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP]); + game.override.enemyMoveset([ Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP, Moves.TAIL_WHIP ]); game.override.battleType("single"); await game.startBattle(); game.move.select(Moves.TACKLE); @@ -259,8 +259,8 @@ describe("Test Battle Phase", () => { game.override.ability(Abilities.ZEN_MODE); game.override.startingLevel(2000); game.override.startingWave(3); - game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.moveset([ moveToUse ]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); await game.startBattle([ Species.DARMANITAN, Species.CHARIZARD, @@ -282,8 +282,8 @@ describe("Test Battle Phase", () => { game.override.ability(Abilities.ZEN_MODE); game.override.startingLevel(2000); game.override.startingWave(3); - game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.moveset([ moveToUse ]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); await game.startBattle(); const turn = game.scene.currentBattle.turn; game.move.select(moveToUse); @@ -302,8 +302,8 @@ describe("Test Battle Phase", () => { .startingLevel(2000) .startingWave(3) .startingBiome(Biome.LAKE) - .moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + .moveset([ moveToUse ]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); await game.classicMode.startBattle(); const waveIndex = game.scene.currentBattle.waveIndex; game.move.select(moveToUse); @@ -323,7 +323,7 @@ describe("Test Battle Phase", () => { .enemySpecies(Species.RATTATA) .startingWave(1) .startingLevel(100) - .moveset([moveToUse]) + .moveset([ moveToUse ]) .enemyMoveset(Moves.SPLASH) .startingHeldItems([{ name: "TEMP_STAT_STAGE_BOOSTER", type: Stat.ACC }]); diff --git a/src/test/battle/damage_calculation.test.ts b/src/test/battle/damage_calculation.test.ts index a348df6c085..e6ecbe4646f 100644 --- a/src/test/battle/damage_calculation.test.ts +++ b/src/test/battle/damage_calculation.test.ts @@ -31,11 +31,11 @@ describe("Battle Mechanics - Damage Calculation", () => { .startingLevel(100) .enemyLevel(100) .disableCrits() - .moveset([Moves.TACKLE, Moves.DRAGON_RAGE, Moves.FISSURE, Moves.JUMP_KICK]); + .moveset([ Moves.TACKLE, Moves.DRAGON_RAGE, Moves.FISSURE, Moves.JUMP_KICK ]); }); it("Tackle deals expected base damage", async () => { - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerPokemon()!; vi.spyOn(playerPokemon, "getEffectiveStat").mockReturnValue(80); @@ -53,7 +53,7 @@ describe("Battle Mechanics - Damage Calculation", () => { .startingLevel(1) .enemySpecies(Species.AGGRON); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const aggron = game.scene.getEnemyPokemon()!; @@ -70,7 +70,7 @@ describe("Battle Mechanics - Damage Calculation", () => { .enemySpecies(Species.DRAGONITE) .enemyAbility(Abilities.MULTISCALE); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const magikarp = game.scene.getPlayerPokemon()!; const dragonite = game.scene.getEnemyPokemon()!; @@ -83,7 +83,7 @@ describe("Battle Mechanics - Damage Calculation", () => { .enemySpecies(Species.AGGRON) .enemyAbility(Abilities.MULTISCALE); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const magikarp = game.scene.getPlayerPokemon()!; const aggron = game.scene.getEnemyPokemon()!; @@ -96,7 +96,7 @@ describe("Battle Mechanics - Damage Calculation", () => { .enemySpecies(Species.GASTLY) .ability(Abilities.WONDER_GUARD); - await game.classicMode.startBattle([Species.SHEDINJA]); + await game.classicMode.startBattle([ Species.SHEDINJA ]); const shedinja = game.scene.getPlayerPokemon()!; @@ -115,7 +115,7 @@ describe("Battle Mechanics - Damage Calculation", () => { .enemySpecies(Species.CHARIZARD) .enemyAbility(Abilities.BLAZE); - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const charizard = game.scene.getEnemyPokemon()!; diff --git a/src/test/battle/error-handling.test.ts b/src/test/battle/error-handling.test.ts index da5cc4d1969..208463e7064 100644 --- a/src/test/battle/error-handling.test.ts +++ b/src/test/battle/error-handling.test.ts @@ -30,8 +30,8 @@ describe("Error Handling", () => { game.override.enemyAbility(Abilities.HYDRATION); game.override.ability(Abilities.ZEN_MODE); game.override.startingLevel(2000); - game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.moveset([ moveToUse ]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); }); it.skip("to next turn", async () => { diff --git a/src/test/battle/inverse_battle.test.ts b/src/test/battle/inverse_battle.test.ts index 01a0348e730..110f92d15b7 100644 --- a/src/test/battle/inverse_battle.test.ts +++ b/src/test/battle/inverse_battle.test.ts @@ -11,7 +11,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; - describe("Inverse Battle", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -42,7 +41,7 @@ describe("Inverse Battle", () => { it("Immune types are 2x effective - Thunderbolt against Ground Type", async () => { game.override - .moveset([Moves.THUNDERBOLT]) + .moveset([ Moves.THUNDERBOLT ]) .enemySpecies(Species.SANDSHREW); @@ -52,7 +51,7 @@ describe("Inverse Battle", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.THUNDERBOLT); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); @@ -60,7 +59,7 @@ describe("Inverse Battle", () => { it("2x effective types are 0.5x effective - Thunderbolt against Flying Type", async () => { game.override - .moveset([Moves.THUNDERBOLT]) + .moveset([ Moves.THUNDERBOLT ]) .enemySpecies(Species.PIDGEY); await game.challengeMode.startBattle(); @@ -69,7 +68,7 @@ describe("Inverse Battle", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.THUNDERBOLT); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(0.5); @@ -77,7 +76,7 @@ describe("Inverse Battle", () => { it("0.5x effective types are 2x effective - Thunderbolt against Electric Type", async () => { game.override - .moveset([Moves.THUNDERBOLT]) + .moveset([ Moves.THUNDERBOLT ]) .enemySpecies(Species.CHIKORITA); await game.challengeMode.startBattle(); @@ -86,7 +85,7 @@ describe("Inverse Battle", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.THUNDERBOLT); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); @@ -114,7 +113,7 @@ describe("Inverse Battle", () => { it("Freeze Dry is 2x effective against Water Type like other Ice type Move - Freeze Dry against Squirtle", async () => { game.override - .moveset([Moves.FREEZE_DRY]) + .moveset([ Moves.FREEZE_DRY ]) .enemySpecies(Species.SQUIRTLE); await game.challengeMode.startBattle(); @@ -123,7 +122,7 @@ describe("Inverse Battle", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.FREEZE_DRY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); @@ -131,7 +130,7 @@ describe("Inverse Battle", () => { it("Water Absorb should heal against water moves - Water Absorb against Water gun", async () => { game.override - .moveset([Moves.WATER_GUN]) + .moveset([ Moves.WATER_GUN ]) .enemyAbility(Abilities.WATER_ABSORB); await game.challengeMode.startBattle(); @@ -139,7 +138,7 @@ describe("Inverse Battle", () => { const enemy = game.scene.getEnemyPokemon()!; enemy.hp = enemy.getMaxHp() - 1; game.move.select(Moves.WATER_GUN); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.hp).toBe(enemy.getMaxHp()); @@ -147,7 +146,7 @@ describe("Inverse Battle", () => { it("Fire type does not get burned - Will-O-Wisp against Charmander", async () => { game.override - .moveset([Moves.WILL_O_WISP]) + .moveset([ Moves.WILL_O_WISP ]) .enemySpecies(Species.CHARMANDER); await game.challengeMode.startBattle(); @@ -155,7 +154,7 @@ describe("Inverse Battle", () => { const enemy = game.scene.getEnemyPokemon()!; game.move.select(Moves.WILL_O_WISP); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.move.forceHit(); await game.phaseInterceptor.to("MoveEndPhase"); @@ -164,7 +163,7 @@ describe("Inverse Battle", () => { it("Electric type does not get paralyzed - Nuzzle against Pikachu", async () => { game.override - .moveset([Moves.NUZZLE]) + .moveset([ Moves.NUZZLE ]) .enemySpecies(Species.PIKACHU) .enemyLevel(50); @@ -173,7 +172,7 @@ describe("Inverse Battle", () => { const enemy = game.scene.getEnemyPokemon()!; game.move.select(Moves.NUZZLE); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.status?.effect).not.toBe(StatusEffect.PARALYSIS); @@ -181,7 +180,7 @@ describe("Inverse Battle", () => { it("Ground type is not immune to Thunder Wave - Thunder Wave against Sandshrew", async () => { game.override - .moveset([Moves.THUNDER_WAVE]) + .moveset([ Moves.THUNDER_WAVE ]) .enemySpecies(Species.SANDSHREW); await game.challengeMode.startBattle(); @@ -189,7 +188,7 @@ describe("Inverse Battle", () => { const enemy = game.scene.getEnemyPokemon()!; game.move.select(Moves.THUNDER_WAVE); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.move.forceHit(); await game.phaseInterceptor.to("MoveEndPhase"); @@ -199,7 +198,7 @@ describe("Inverse Battle", () => { it("Anticipation should trigger on 2x effective moves - Anticipation against Thunderbolt", async () => { game.override - .moveset([Moves.THUNDERBOLT]) + .moveset([ Moves.THUNDERBOLT ]) .enemySpecies(Species.SANDSHREW) .enemyAbility(Abilities.ANTICIPATION); @@ -210,15 +209,15 @@ describe("Inverse Battle", () => { it("Conversion 2 should change the type to the resistive type - Conversion 2 against Dragonite", async () => { game.override - .moveset([Moves.CONVERSION_2]) - .enemyMoveset([Moves.DRAGON_CLAW, Moves.DRAGON_CLAW, Moves.DRAGON_CLAW, Moves.DRAGON_CLAW]); + .moveset([ Moves.CONVERSION_2 ]) + .enemyMoveset([ Moves.DRAGON_CLAW, Moves.DRAGON_CLAW, Moves.DRAGON_CLAW, Moves.DRAGON_CLAW ]); await game.challengeMode.startBattle(); const player = game.scene.getPlayerPokemon()!; game.move.select(Moves.CONVERSION_2); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase"); @@ -227,7 +226,7 @@ describe("Inverse Battle", () => { it("Flying Press should be 0.25x effective against Grass + Dark Type - Flying Press against Meowscarada", async () => { game.override - .moveset([Moves.FLYING_PRESS]) + .moveset([ Moves.FLYING_PRESS ]) .enemySpecies(Species.MEOWSCARADA); await game.challengeMode.startBattle(); @@ -236,7 +235,7 @@ describe("Inverse Battle", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.FLYING_PRESS); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(0.25); @@ -244,7 +243,7 @@ describe("Inverse Battle", () => { it("Scrappy ability has no effect - Tackle against Ghost Type still 2x effective with Scrappy", async () => { game.override - .moveset([Moves.TACKLE]) + .moveset([ Moves.TACKLE ]) .ability(Abilities.SCRAPPY) .enemySpecies(Species.GASTLY); @@ -254,7 +253,7 @@ describe("Inverse Battle", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.TACKLE); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); @@ -262,7 +261,7 @@ describe("Inverse Battle", () => { it("FORESIGHT has no effect - Tackle against Ghost Type still 2x effective with Foresight", async () => { game.override - .moveset([Moves.FORESIGHT, Moves.TACKLE]) + .moveset([ Moves.FORESIGHT, Moves.TACKLE ]) .enemySpecies(Species.GASTLY); await game.challengeMode.startBattle(); @@ -271,11 +270,11 @@ describe("Inverse Battle", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.FORESIGHT); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase"); game.move.select(Moves.TACKLE); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveLastReturnedWith(2); diff --git a/src/test/battle/special_battle.test.ts b/src/test/battle/special_battle.test.ts index 1d319bea372..af9e3dddbec 100644 --- a/src/test/battle/special_battle.test.ts +++ b/src/test/battle/special_battle.test.ts @@ -25,10 +25,10 @@ describe("Test Battle Phase", () => { game = new GameManager(phaserGame); game.override.enemySpecies(Species.RATTATA); game.override.startingLevel(2000); - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); game.override.enemyAbility(Abilities.HYDRATION); game.override.ability(Abilities.HYDRATION); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); }); it("startBattle 2vs1 boss", async() => { diff --git a/src/test/battlerTags/stockpiling.test.ts b/src/test/battlerTags/stockpiling.test.ts index ae2528e7b5f..dab189853c5 100644 --- a/src/test/battlerTags/stockpiling.test.ts +++ b/src/test/battlerTags/stockpiling.test.ts @@ -27,7 +27,7 @@ describe("BattlerTag - StockpilingTag", () => { expect((phase as StatStageChangePhase)["stages"]).toEqual(1); expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.DEF, Stat.SPDEF ])); - (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [Stat.DEF, Stat.SPDEF], [1, 1]); + (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.DEF, Stat.SPDEF ], [ 1, 1 ]); }); subject.onAdd(mockPokemon); @@ -52,9 +52,9 @@ describe("BattlerTag - StockpilingTag", () => { vi.spyOn(mockPokemon.scene, "unshiftPhase").mockImplementation(phase => { expect(phase).toBeInstanceOf(StatStageChangePhase); expect((phase as StatStageChangePhase)["stages"]).toEqual(1); - expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([Stat.DEF, Stat.SPDEF])); + expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.DEF, Stat.SPDEF ])); - (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.DEF, Stat.SPDEF ], [1, 1]); + (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.DEF, Stat.SPDEF ], [ 1, 1 ]); }); subject.onAdd(mockPokemon); @@ -79,7 +79,7 @@ describe("BattlerTag - StockpilingTag", () => { expect((phase as StatStageChangePhase)["stages"]).toEqual(1); expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.DEF, Stat.SPDEF ])); - (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.DEF, Stat.SPDEF ], [1, 1]); + (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.DEF, Stat.SPDEF ], [ 1, 1 ]); }); subject.onOverlap(mockPokemon); @@ -109,7 +109,7 @@ describe("BattlerTag - StockpilingTag", () => { expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.DEF, Stat.SPDEF ])); // def doesn't change - (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.SPDEF ], [1]); + (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.SPDEF ], [ 1 ]); }); subject.onAdd(mockPokemon); @@ -121,7 +121,7 @@ describe("BattlerTag - StockpilingTag", () => { expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.DEF, Stat.SPDEF ])); // def doesn't change - (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.SPDEF ], [1]); + (phase as StatStageChangePhase)["onChange"]!(mockPokemon, [ Stat.SPDEF ], [ 1 ]); }); subject.onOverlap(mockPokemon); @@ -145,13 +145,13 @@ describe("BattlerTag - StockpilingTag", () => { // fourth stack should not be applied subject.onOverlap(mockPokemon); expect(subject.stockpiledCount).toBe(3); - expect(subject.statChangeCounts).toMatchObject({ [ Stat.DEF ]: 0, [Stat.SPDEF]: 2 }); + expect(subject.statChangeCounts).toMatchObject({ [Stat.DEF]: 0, [Stat.SPDEF]: 2 }); // removing tag should reverse stat changes vi.spyOn(mockPokemon.scene, "unshiftPhase").mockImplementationOnce(phase => { expect(phase).toBeInstanceOf(StatStageChangePhase); expect((phase as StatStageChangePhase)["stages"]).toEqual(-2); - expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([Stat.SPDEF])); + expect((phase as StatStageChangePhase)["stats"]).toEqual(expect.arrayContaining([ Stat.SPDEF ])); }); subject.onRemove(mockPokemon); diff --git a/src/test/battlerTags/substitute.test.ts b/src/test/battlerTags/substitute.test.ts index 0802b549823..af0aa63af89 100644 --- a/src/test/battlerTags/substitute.test.ts +++ b/src/test/battlerTags/substitute.test.ts @@ -122,8 +122,8 @@ describe("BattlerTag - SubstituteTag", () => { scene: new BattleScene(), hp: 101, id: 0, - turnData: {acted: true} as PokemonTurnData, - getLastXMoves: vi.fn().mockReturnValue([{move: Moves.TACKLE, result: MoveResult.SUCCESS} as TurnMove]) as Pokemon["getLastXMoves"], + turnData: { acted: true } as PokemonTurnData, + getLastXMoves: vi.fn().mockReturnValue([ { move: Moves.TACKLE, result: MoveResult.SUCCESS } as TurnMove ]) as Pokemon["getLastXMoves"], } as Pokemon; vi.spyOn(messages, "getPokemonNameWithAffix").mockReturnValue(""); diff --git a/src/test/boss-pokemon.test.ts b/src/test/boss-pokemon.test.ts index e316cac0cf6..840b65f3cc6 100644 --- a/src/test/boss-pokemon.test.ts +++ b/src/test/boss-pokemon.test.ts @@ -33,7 +33,7 @@ describe("Boss Pokemon / Shields", () => { .enemyMoveset(Moves.SPLASH) .enemyHeldItems([]) .startingLevel(1000) - .moveset([Moves.FALSE_SWIPE, Moves.SUPER_FANG, Moves.SPLASH, Moves.PSYCHIC]) + .moveset([ Moves.FALSE_SWIPE, Moves.SUPER_FANG, Moves.SPLASH, Moves.PSYCHIC ]) .ability(Abilities.NO_GUARD); }); @@ -172,7 +172,7 @@ describe("Boss Pokemon / Shields", () => { game.move.select(Moves.SPLASH); await game.toNextTurn(); // All broken shields give +1 stat boost, except the last two that gives +2 - totalStatStages += i >= shieldsToBreak -1? 2 : 1; + totalStatStages += i >= shieldsToBreak - 1 ? 2 : 1; expect(getTotalStatStageBoosts(boss1)).toBe(totalStatStages); } diff --git a/src/test/daily_mode.test.ts b/src/test/daily_mode.test.ts index 58692330272..100cf07f9c0 100644 --- a/src/test/daily_mode.test.ts +++ b/src/test/daily_mode.test.ts @@ -5,6 +5,7 @@ import { Moves } from "#app/enums/moves"; import { Biome } from "#app/enums/biome"; import { Mode } from "#app/ui/ui"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; +import { Species } from "#enums/species"; //const TIMEOUT = 20 * 1000; @@ -53,12 +54,11 @@ describe("Shop modifications", async () => { game.override .startingWave(9) - .startingBiome(Biome.ICE_CAVE) // Will lead to Snowy Forest with randomly generated weather + .startingBiome(Biome.ICE_CAVE) .battleType("single") .startingLevel(100) // Avoid levelling up - .enemyLevel(1000) // Avoid opponent dying before game.doKillOpponents() .disableTrainerWaves() - .moveset([Moves.KOWTOW_CLEAVE]) + .moveset([ Moves.SPLASH ]) .enemyMoveset(Moves.SPLASH); game.modifiers .addCheck("EVIOLITE") @@ -71,9 +71,8 @@ describe("Shop modifications", async () => { }); it("should not have Eviolite and Mini Black Hole available in Classic if not unlocked", async () => { - await game.classicMode.startBattle(); - game.move.select(Moves.KOWTOW_CLEAVE); - await game.phaseInterceptor.to("DamagePhase"); + await game.classicMode.startBattle([ Species.BULBASAUR ]); + game.move.select(Moves.SPLASH); await game.doKillOpponents(); await game.phaseInterceptor.to("BattleEndPhase"); game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => { @@ -86,8 +85,7 @@ describe("Shop modifications", async () => { it("should have Eviolite and Mini Black Hole available in Daily", async () => { await game.dailyMode.startBattle(); - game.move.select(Moves.KOWTOW_CLEAVE); - await game.phaseInterceptor.to("DamagePhase"); + game.move.select(Moves.SPLASH); await game.doKillOpponents(); await game.phaseInterceptor.to("BattleEndPhase"); game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => { diff --git a/src/test/data/splash_messages.test.ts b/src/test/data/splash_messages.test.ts index 7e07b9a6e77..b9ed5b9d365 100644 --- a/src/test/data/splash_messages.test.ts +++ b/src/test/data/splash_messages.test.ts @@ -51,8 +51,8 @@ function testSeason(startDate: Date, endDate: Date, prefix: string) { const afterDate = new Date(endDate); afterDate.setDate(endDate.getDate() + 1); - const dates: Date[] = [beforeDate, startDate, endDate, afterDate]; - const [before, start, end, after] = dates.map((date) => { + const dates: Date[] = [ beforeDate, startDate, endDate, afterDate ]; + const [ before, start, end, after ] = dates.map((date) => { vi.setSystemTime(date); console.log("System time set to", date); const count = getSplashMessages().filter(filterFn).length; diff --git a/src/test/eggs/egg.test.ts b/src/test/eggs/egg.test.ts index 053ff8f1112..6f57af63e6b 100644 --- a/src/test/eggs/egg.test.ts +++ b/src/test/eggs/egg.test.ts @@ -55,7 +55,7 @@ describe("Egg Generation Tests", () => { let gachaSpeciesCount = 0; for (let i = 0; i < EGG_HATCH_COUNT; i++) { - const result = new Egg({ scene, timestamp, sourceType: EggSourceType.GACHA_LEGENDARY, tier: EggTier.MASTER }).generatePlayerPokemon(scene).species.speciesId; + const result = new Egg({ scene, timestamp, sourceType: EggSourceType.GACHA_LEGENDARY, tier: EggTier.LEGENDARY }).generatePlayerPokemon(scene).species.speciesId; if (result === expectedSpecies) { gachaSpeciesCount++; } @@ -82,7 +82,7 @@ describe("Egg Generation Tests", () => { }); it("should return an rare tier egg", () => { const scene = game.scene; - const expectedTier = EggTier.GREAT; + const expectedTier = EggTier.RARE; const result = new Egg({ scene, tier: expectedTier }).tier; @@ -90,7 +90,7 @@ describe("Egg Generation Tests", () => { }); it("should return an epic tier egg", () => { const scene = game.scene; - const expectedTier = EggTier.ULTRA; + const expectedTier = EggTier.EPIC; const result = new Egg({ scene, tier: expectedTier }).tier; @@ -98,7 +98,7 @@ describe("Egg Generation Tests", () => { }); it("should return an legendary tier egg", () => { const scene = game.scene; - const expectedTier = EggTier.MASTER; + const expectedTier = EggTier.LEGENDARY; const result = new Egg({ scene, tier: expectedTier }).tier; @@ -200,7 +200,7 @@ describe("Egg Generation Tests", () => { const scene = game.scene; const expectedEggTier = EggTier.COMMON; - const result = new Egg({ scene, tier: EggTier.MASTER, species: Species.BULBASAUR }).tier; + const result = new Egg({ scene, tier: EggTier.LEGENDARY, species: Species.BULBASAUR }).tier; expect(result).toBe(expectedEggTier); }); @@ -208,7 +208,7 @@ describe("Egg Generation Tests", () => { const scene = game.scene; const expectedHatchWaves = 10; - const result = new Egg({ scene, tier: EggTier.MASTER, species: Species.BULBASAUR }).hatchWaves; + const result = new Egg({ scene, tier: EggTier.LEGENDARY, species: Species.BULBASAUR }).hatchWaves; expect(result).toBe(expectedHatchWaves); }); @@ -229,7 +229,7 @@ describe("Egg Generation Tests", () => { const result = new EggData(legacyEgg).toEgg(); - expect(result.tier).toBe(EggTier.GREAT); + expect(result.tier).toBe(EggTier.RARE); expect(result.id).toBe(legacyEgg.id); expect(result.timestamp).toBe(legacyEgg.timestamp); expect(result.hatchWaves).toBe(legacyEgg.hatchWaves); @@ -237,23 +237,23 @@ describe("Egg Generation Tests", () => { }); it("should increase egg pity", () => { const scene = game.scene; - const startPityValues = [...scene.gameData.eggPity]; + const startPityValues = [ ...scene.gameData.eggPity ]; new Egg({ scene, sourceType: EggSourceType.GACHA_MOVE, pulled: true, tier: EggTier.COMMON }); - expect(scene.gameData.eggPity[EggTier.GREAT]).toBe(startPityValues[EggTier.GREAT] + 1); - expect(scene.gameData.eggPity[EggTier.ULTRA]).toBe(startPityValues[EggTier.ULTRA] + 1); - expect(scene.gameData.eggPity[EggTier.MASTER]).toBe(startPityValues[EggTier.MASTER] + 1); + expect(scene.gameData.eggPity[EggTier.RARE]).toBe(startPityValues[EggTier.RARE] + 1); + expect(scene.gameData.eggPity[EggTier.EPIC]).toBe(startPityValues[EggTier.EPIC] + 1); + expect(scene.gameData.eggPity[EggTier.LEGENDARY]).toBe(startPityValues[EggTier.LEGENDARY] + 1); }); it("should increase legendary egg pity by two", () => { const scene = game.scene; - const startPityValues = [...scene.gameData.eggPity]; + const startPityValues = [ ...scene.gameData.eggPity ]; new Egg({ scene, sourceType: EggSourceType.GACHA_LEGENDARY, pulled: true, tier: EggTier.COMMON }); - expect(scene.gameData.eggPity[EggTier.GREAT]).toBe(startPityValues[EggTier.GREAT] + 1); - expect(scene.gameData.eggPity[EggTier.ULTRA]).toBe(startPityValues[EggTier.ULTRA] + 1); - expect(scene.gameData.eggPity[EggTier.MASTER]).toBe(startPityValues[EggTier.MASTER] + 2); + expect(scene.gameData.eggPity[EggTier.RARE]).toBe(startPityValues[EggTier.RARE] + 1); + expect(scene.gameData.eggPity[EggTier.EPIC]).toBe(startPityValues[EggTier.EPIC] + 1); + expect(scene.gameData.eggPity[EggTier.LEGENDARY]).toBe(startPityValues[EggTier.LEGENDARY] + 2); }); it("should not increase manaphy egg count if bulbasaurs are pulled", () => { const scene = game.scene; @@ -277,7 +277,7 @@ describe("Egg Generation Tests", () => { const scene = game.scene; const startingRareEggsPulled = scene.gameData.gameStats.rareEggsPulled; - new Egg({ scene, sourceType: EggSourceType.GACHA_MOVE, pulled: true, tier: EggTier.GREAT }); + new Egg({ scene, sourceType: EggSourceType.GACHA_MOVE, pulled: true, tier: EggTier.RARE }); expect(scene.gameData.gameStats.rareEggsPulled).toBe(startingRareEggsPulled + 1); }); @@ -285,7 +285,7 @@ describe("Egg Generation Tests", () => { const scene = game.scene; const startingEpicEggsPulled = scene.gameData.gameStats.epicEggsPulled; - new Egg({ scene, sourceType: EggSourceType.GACHA_MOVE, pulled: true, tier: EggTier.ULTRA }); + new Egg({ scene, sourceType: EggSourceType.GACHA_MOVE, pulled: true, tier: EggTier.EPIC }); expect(scene.gameData.gameStats.epicEggsPulled).toBe(startingEpicEggsPulled + 1); }); @@ -293,7 +293,7 @@ describe("Egg Generation Tests", () => { const scene = game.scene; const startingLegendaryEggsPulled = scene.gameData.gameStats.legendaryEggsPulled; - new Egg({ scene, sourceType: EggSourceType.GACHA_MOVE, pulled: true, tier: EggTier.MASTER }); + new Egg({ scene, sourceType: EggSourceType.GACHA_MOVE, pulled: true, tier: EggTier.LEGENDARY }); expect(scene.gameData.gameStats.legendaryEggsPulled).toBe(startingLegendaryEggsPulled + 1); }); @@ -301,8 +301,8 @@ describe("Egg Generation Tests", () => { vi.spyOn(Utils, "randInt").mockReturnValue(1); const scene = game.scene; - const expectedTier1 = EggTier.MASTER; - const expectedTier2 = EggTier.ULTRA; + const expectedTier1 = EggTier.LEGENDARY; + const expectedTier2 = EggTier.EPIC; const result1 = new Egg({ scene, sourceType: EggSourceType.GACHA_LEGENDARY, pulled: true }).tier; const result2 = new Egg({ scene, sourceType: EggSourceType.GACHA_MOVE, pulled: true }).tier; @@ -323,7 +323,7 @@ describe("Egg Generation Tests", () => { scene.setSeed("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); scene.resetSeed(); - const firstEgg = new Egg({scene, sourceType: EggSourceType.GACHA_SHINY, tier: EggTier.COMMON}); + const firstEgg = new Egg({ scene, sourceType: EggSourceType.GACHA_SHINY, tier: EggTier.COMMON }); const firstHatch = firstEgg.generatePlayerPokemon(scene); let diffEggMove = false; let diffSpecies = false; @@ -334,7 +334,7 @@ describe("Egg Generation Tests", () => { scene.setSeed("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); scene.resetSeed(); // Make sure that eggs are unpredictable even if using same seed - const newEgg = new Egg({scene, sourceType: EggSourceType.GACHA_SHINY, tier: EggTier.COMMON}); + const newEgg = new Egg({ scene, sourceType: EggSourceType.GACHA_SHINY, tier: EggTier.COMMON }); const newHatch = newEgg.generatePlayerPokemon(scene); diffEggMove = diffEggMove || (newEgg.eggMoveIndex !== firstEgg.eggMoveIndex); diffSpecies = diffSpecies || (newHatch.species.speciesId !== firstHatch.species.speciesId); @@ -353,7 +353,7 @@ describe("Egg Generation Tests", () => { scene.setSeed("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); scene.resetSeed(); - const firstEgg = new Egg({scene, species: Species.BULBASAUR}); + const firstEgg = new Egg({ scene, species: Species.BULBASAUR }); const firstHatch = firstEgg.generatePlayerPokemon(scene); let diffEggMove = false; let diffSpecies = false; @@ -363,7 +363,7 @@ describe("Egg Generation Tests", () => { scene.setSeed("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); scene.resetSeed(); // Make sure that eggs are unpredictable even if using same seed - const newEgg = new Egg({scene, species: Species.BULBASAUR}); + const newEgg = new Egg({ scene, species: Species.BULBASAUR }); const newHatch = newEgg.generatePlayerPokemon(scene); diffEggMove = diffEggMove || (newEgg.eggMoveIndex !== firstEgg.eggMoveIndex); diffSpecies = diffSpecies || (newHatch.species.speciesId !== firstHatch.species.speciesId); diff --git a/src/test/eggs/manaphy-egg.test.ts b/src/test/eggs/manaphy-egg.test.ts index 257bf330bb8..3b2c40ae84a 100644 --- a/src/test/eggs/manaphy-egg.test.ts +++ b/src/test/eggs/manaphy-egg.test.ts @@ -60,8 +60,8 @@ describe("Manaphy Eggs", () => { } expect(manaphyCount + phioneCount).toBe(EGG_HATCH_COUNT); - expect(manaphyCount).toBe(1/8 * EGG_HATCH_COUNT); - expect(rareEggMoveCount).toBe(1/12 * EGG_HATCH_COUNT); + expect(manaphyCount).toBe(1 / 8 * EGG_HATCH_COUNT); + expect(rareEggMoveCount).toBe(1 / 12 * EGG_HATCH_COUNT); }); it("should have correct Manaphy rates and Rare Egg Move rates, from Phione species eggs", () => { @@ -86,8 +86,8 @@ describe("Manaphy Eggs", () => { } expect(manaphyCount + phioneCount).toBe(EGG_HATCH_COUNT); - expect(manaphyCount).toBe(1/8 * EGG_HATCH_COUNT); - expect(rareEggMoveCount).toBe(1/6 * EGG_HATCH_COUNT); + expect(manaphyCount).toBe(1 / 8 * EGG_HATCH_COUNT); + expect(rareEggMoveCount).toBe(1 / 6 * EGG_HATCH_COUNT); }); it("should have correct Manaphy rates and Rare Egg Move rates, from Manaphy species eggs", () => { @@ -113,6 +113,6 @@ describe("Manaphy Eggs", () => { expect(phioneCount).toBe(0); expect(manaphyCount).toBe(EGG_HATCH_COUNT); - expect(rareEggMoveCount).toBe(1/6 * EGG_HATCH_COUNT); + expect(rareEggMoveCount).toBe(1 / 6 * EGG_HATCH_COUNT); }); }); diff --git a/src/test/endless_boss.test.ts b/src/test/endless_boss.test.ts index 8a564695e42..c9f3afc3936 100644 --- a/src/test/endless_boss.test.ts +++ b/src/test/endless_boss.test.ts @@ -32,7 +32,7 @@ describe("Endless Boss", () => { it(`should spawn a minor boss every ${EndlessBossWave.Minor} waves in END biome in Endless`, async () => { game.override.startingWave(EndlessBossWave.Minor); - await game.runToFinalBossEncounter([Species.BIDOOF], GameModes.ENDLESS); + await game.runToFinalBossEncounter([ Species.BIDOOF ], GameModes.ENDLESS); expect(game.scene.currentBattle.waveIndex).toBe(EndlessBossWave.Minor); expect(game.scene.arena.biomeType).toBe(Biome.END); @@ -44,7 +44,7 @@ describe("Endless Boss", () => { it(`should spawn a major boss every ${EndlessBossWave.Major} waves in END biome in Endless`, async () => { game.override.startingWave(EndlessBossWave.Major); - await game.runToFinalBossEncounter([Species.BIDOOF], GameModes.ENDLESS); + await game.runToFinalBossEncounter([ Species.BIDOOF ], GameModes.ENDLESS); expect(game.scene.currentBattle.waveIndex).toBe(EndlessBossWave.Major); expect(game.scene.arena.biomeType).toBe(Biome.END); @@ -56,7 +56,7 @@ describe("Endless Boss", () => { it(`should spawn a minor boss every ${EndlessBossWave.Minor} waves in END biome in Spliced Endless`, async () => { game.override.startingWave(EndlessBossWave.Minor); - await game.runToFinalBossEncounter([Species.BIDOOF], GameModes.SPLICED_ENDLESS); + await game.runToFinalBossEncounter([ Species.BIDOOF ], GameModes.SPLICED_ENDLESS); expect(game.scene.currentBattle.waveIndex).toBe(EndlessBossWave.Minor); expect(game.scene.arena.biomeType).toBe(Biome.END); @@ -68,7 +68,7 @@ describe("Endless Boss", () => { it(`should spawn a major boss every ${EndlessBossWave.Major} waves in END biome in Spliced Endless`, async () => { game.override.startingWave(EndlessBossWave.Major); - await game.runToFinalBossEncounter([Species.BIDOOF], GameModes.SPLICED_ENDLESS); + await game.runToFinalBossEncounter([ Species.BIDOOF ], GameModes.SPLICED_ENDLESS); expect(game.scene.currentBattle.waveIndex).toBe(EndlessBossWave.Major); expect(game.scene.arena.biomeType).toBe(Biome.END); @@ -80,7 +80,7 @@ describe("Endless Boss", () => { it(`should NOT spawn major or minor boss outside wave ${EndlessBossWave.Minor}s in END biome`, async () => { game.override.startingWave(EndlessBossWave.Minor - 1); - await game.runToFinalBossEncounter([Species.BIDOOF], GameModes.ENDLESS); + await game.runToFinalBossEncounter([ Species.BIDOOF ], GameModes.ENDLESS); expect(game.scene.currentBattle.waveIndex).not.toBe(EndlessBossWave.Minor); expect(game.scene.getEnemyPokemon()!.species.speciesId).not.toBe(Species.ETERNATUS); diff --git a/src/test/enemy_command.test.ts b/src/test/enemy_command.test.ts index 53cddc86efb..49419f5b34d 100644 --- a/src/test/enemy_command.test.ts +++ b/src/test/enemy_command.test.ts @@ -23,7 +23,7 @@ function getEnemyMoveChoices(pokemon: EnemyPokemon, moveChoices: MoveChoiceSet): moveChoices[queuedMove.move]++; } - for (const [moveId, count] of Object.entries(moveChoices)) { + for (const [ moveId, count ] of Object.entries(moveChoices)) { console.log(`Move: ${allMoves[moveId].name} Count: ${count} (${count / NUM_TRIALS * 100}%)`); } } @@ -55,11 +55,11 @@ describe("Enemy Commands - Move Selection", () => { async () => { game.override .enemySpecies(Species.ETERNATUS) - .enemyMoveset([Moves.ETERNABEAM, Moves.SLUDGE_BOMB, Moves.DRAGON_DANCE, Moves.COSMIC_POWER]) + .enemyMoveset([ Moves.ETERNABEAM, Moves.SLUDGE_BOMB, Moves.DRAGON_DANCE, Moves.COSMIC_POWER ]) .startingLevel(1) .enemyLevel(100); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const enemyPokemon = game.scene.getEnemyPokemon()!; enemyPokemon.aiType = AiType.SMART_RANDOM; @@ -82,11 +82,11 @@ describe("Enemy Commands - Move Selection", () => { async () => { game.override .enemySpecies(Species.KANGASKHAN) - .enemyMoveset([Moves.LAST_RESORT, Moves.GIGA_IMPACT, Moves.SPLASH, Moves.SWORDS_DANCE]) + .enemyMoveset([ Moves.LAST_RESORT, Moves.GIGA_IMPACT, Moves.SPLASH, Moves.SWORDS_DANCE ]) .startingLevel(1) .enemyLevel(100); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const enemyPokemon = game.scene.getEnemyPokemon()!; enemyPokemon.aiType = AiType.SMART_RANDOM; diff --git a/src/test/escape-calculations.test.ts b/src/test/escape-calculations.test.ts index ecf22fc74aa..cc18fd78066 100644 --- a/src/test/escape-calculations.test.ts +++ b/src/test/escape-calculations.test.ts @@ -32,13 +32,13 @@ describe("Escape chance calculations", () => { }); it("single non-boss opponent", async () => { - await game.classicMode.startBattle([Species.BULBASAUR]); + await game.classicMode.startBattle([ Species.BULBASAUR ]); const playerPokemon = game.scene.getPlayerField(); const enemyField = game.scene.getEnemyField(); const enemySpeed = 100; // set enemyPokemon's speed to 100 - vi.spyOn(enemyField[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, enemySpeed]); + vi.spyOn(enemyField[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, enemySpeed ]); const commandPhase = game.scene.getCurrentPhase() as CommandPhase; commandPhase.handleCommand(Command.RUN, 0); @@ -79,7 +79,7 @@ describe("Escape chance calculations", () => { // sets the number of escape attempts to the required amount game.scene.currentBattle.escapeAttempts = escapeChances[i].escapeAttempts; // set playerPokemon's speed to a multiple of the enemySpeed - vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, escapeChances[i].pokemonSpeedRatio * enemySpeed]); + vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, escapeChances[i].pokemonSpeedRatio * enemySpeed ]); phase.attemptRunAway(playerPokemon, enemyField, escapePercentage); expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance); } @@ -87,7 +87,7 @@ describe("Escape chance calculations", () => { it("double non-boss opponent", async () => { game.override.battleType("double"); - await game.classicMode.startBattle([Species.BULBASAUR, Species.ABOMASNOW]); + await game.classicMode.startBattle([ Species.BULBASAUR, Species.ABOMASNOW ]); const playerPokemon = game.scene.getPlayerField(); const enemyField = game.scene.getEnemyField(); @@ -98,9 +98,9 @@ describe("Escape chance calculations", () => { // this is used to find the ratio of the player's first pokemon const playerASpeedPercentage = 0.4; // set enemyAPokemon's speed to 70 - vi.spyOn(enemyField[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, enemyASpeed]); + vi.spyOn(enemyField[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, enemyASpeed ]); // set enemyBPokemon's speed to 30 - vi.spyOn(enemyField[1], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, enemyBSpeed]); + vi.spyOn(enemyField[1], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, enemyBSpeed ]); const commandPhase = game.scene.getCurrentPhase() as CommandPhase; commandPhase.handleCommand(Command.RUN, 0); @@ -141,9 +141,9 @@ describe("Escape chance calculations", () => { // sets the number of escape attempts to the required amount game.scene.currentBattle.escapeAttempts = escapeChances[i].escapeAttempts; // set the first playerPokemon's speed to a multiple of the enemySpeed - vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, Math.floor(escapeChances[i].pokemonSpeedRatio * totalEnemySpeed * playerASpeedPercentage)]); + vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, Math.floor(escapeChances[i].pokemonSpeedRatio * totalEnemySpeed * playerASpeedPercentage) ]); // set the second playerPokemon's speed to the remaining value of speed - vi.spyOn(playerPokemon[1], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, escapeChances[i].pokemonSpeedRatio * totalEnemySpeed - playerPokemon[0].stats[5]]); + vi.spyOn(playerPokemon[1], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, escapeChances[i].pokemonSpeedRatio * totalEnemySpeed - playerPokemon[0].stats[5] ]); phase.attemptRunAway(playerPokemon, enemyField, escapePercentage); // checks to make sure the escape values are the same expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance); @@ -154,13 +154,13 @@ describe("Escape chance calculations", () => { it("single boss opponent", async () => { game.override.startingWave(10); - await game.classicMode.startBattle([Species.BULBASAUR]); + await game.classicMode.startBattle([ Species.BULBASAUR ]); const playerPokemon = game.scene.getPlayerField()!; const enemyField = game.scene.getEnemyField()!; const enemySpeed = 100; // set enemyPokemon's speed to 100 - vi.spyOn(enemyField[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, enemySpeed]); + vi.spyOn(enemyField[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, enemySpeed ]); const commandPhase = game.scene.getCurrentPhase() as CommandPhase; commandPhase.handleCommand(Command.RUN, 0); @@ -215,7 +215,7 @@ describe("Escape chance calculations", () => { // sets the number of escape attempts to the required amount game.scene.currentBattle.escapeAttempts = escapeChances[i].escapeAttempts; // set playerPokemon's speed to a multiple of the enemySpeed - vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, escapeChances[i].pokemonSpeedRatio * enemySpeed]); + vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, escapeChances[i].pokemonSpeedRatio * enemySpeed ]); phase.attemptRunAway(playerPokemon, enemyField, escapePercentage); expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance); } @@ -224,7 +224,7 @@ describe("Escape chance calculations", () => { it("double boss opponent", async () => { game.override.battleType("double"); game.override.startingWave(10); - await game.classicMode.startBattle([Species.BULBASAUR, Species.ABOMASNOW]); + await game.classicMode.startBattle([ Species.BULBASAUR, Species.ABOMASNOW ]); const playerPokemon = game.scene.getPlayerField(); const enemyField = game.scene.getEnemyField(); @@ -235,9 +235,9 @@ describe("Escape chance calculations", () => { // this is used to find the ratio of the player's first pokemon const playerASpeedPercentage = 0.8; // set enemyAPokemon's speed to 70 - vi.spyOn(enemyField[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, enemyASpeed]); + vi.spyOn(enemyField[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, enemyASpeed ]); // set enemyBPokemon's speed to 30 - vi.spyOn(enemyField[1], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, enemyBSpeed]); + vi.spyOn(enemyField[1], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, enemyBSpeed ]); const commandPhase = game.scene.getCurrentPhase() as CommandPhase; commandPhase.handleCommand(Command.RUN, 0); @@ -290,9 +290,9 @@ describe("Escape chance calculations", () => { // sets the number of escape attempts to the required amount game.scene.currentBattle.escapeAttempts = escapeChances[i].escapeAttempts; // set the first playerPokemon's speed to a multiple of the enemySpeed - vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, Math.floor(escapeChances[i].pokemonSpeedRatio * totalEnemySpeed * playerASpeedPercentage)]); + vi.spyOn(playerPokemon[0], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, Math.floor(escapeChances[i].pokemonSpeedRatio * totalEnemySpeed * playerASpeedPercentage) ]); // set the second playerPokemon's speed to the remaining value of speed - vi.spyOn(playerPokemon[1], "stats", "get").mockReturnValue([20, 20, 20, 20, 20, escapeChances[i].pokemonSpeedRatio * totalEnemySpeed - playerPokemon[0].stats[5]]); + vi.spyOn(playerPokemon[1], "stats", "get").mockReturnValue([ 20, 20, 20, 20, 20, escapeChances[i].pokemonSpeedRatio * totalEnemySpeed - playerPokemon[0].stats[5] ]); phase.attemptRunAway(playerPokemon, enemyField, escapePercentage); // checks to make sure the escape values are the same expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance); diff --git a/src/test/evolution.test.ts b/src/test/evolution.test.ts index 1a5a2be996f..b94d45d6537 100644 --- a/src/test/evolution.test.ts +++ b/src/test/evolution.test.ts @@ -33,7 +33,7 @@ describe("Evolution", () => { }); it("should keep hidden ability after evolving", async () => { - await game.classicMode.runToSummon([Species.EEVEE, Species.TRAPINCH]); + await game.classicMode.runToSummon([ Species.EEVEE, Species.TRAPINCH ]); const eevee = game.scene.getParty()[0]; const trapinch = game.scene.getParty()[1]; @@ -48,7 +48,7 @@ describe("Evolution", () => { }); it("should keep same ability slot after evolving", async () => { - await game.classicMode.runToSummon([Species.BULBASAUR, Species.CHARMANDER]); + await game.classicMode.runToSummon([ Species.BULBASAUR, Species.CHARMANDER ]); const bulbasaur = game.scene.getParty()[0]; const charmander = game.scene.getParty()[1]; @@ -63,7 +63,7 @@ describe("Evolution", () => { }); it("should handle illegal abilityIndex values", async () => { - await game.classicMode.runToSummon([Species.SQUIRTLE]); + await game.classicMode.runToSummon([ Species.SQUIRTLE ]); const squirtle = game.scene.getPlayerPokemon()!; squirtle.abilityIndex = 5; @@ -73,7 +73,7 @@ describe("Evolution", () => { }); it("should handle nincada's unique evolution", async () => { - await game.classicMode.runToSummon([Species.NINCADA]); + await game.classicMode.runToSummon([ Species.NINCADA ]); const nincada = game.scene.getPlayerPokemon()!; nincada.abilityIndex = 2; @@ -95,14 +95,14 @@ describe("Evolution", () => { }); it("should increase both HP and max HP when evolving", async () => { - game.override.moveset([Moves.SURF]) + game.override.moveset([ Moves.SURF ]) .enemySpecies(Species.GOLEM) .enemyMoveset(Moves.SPLASH) .startingWave(21) .startingLevel(16) .enemyLevel(50); - await game.startBattle([Species.TOTODILE]); + await game.startBattle([ Species.TOTODILE ]); const totodile = game.scene.getPlayerPokemon()!; const hpBefore = totodile.hp; @@ -122,14 +122,14 @@ describe("Evolution", () => { }); it("should not fully heal HP when evolving", async () => { - game.override.moveset([Moves.SURF]) + game.override.moveset([ Moves.SURF ]) .enemySpecies(Species.GOLEM) .enemyMoveset(Moves.SPLASH) .startingWave(21) .startingLevel(13) .enemyLevel(30); - await game.startBattle([Species.CYNDAQUIL]); + await game.startBattle([ Species.CYNDAQUIL ]); const cyndaquil = game.scene.getPlayerPokemon()!; cyndaquil.hp = Math.floor(cyndaquil.getMaxHp() / 2); @@ -162,7 +162,7 @@ describe("Evolution", () => { * If the value is 0, it's a 3 family maushold, whereas if the value is * 1, 2 or 3, it's a 4 family maushold */ - await game.startBattle([Species.TANDEMAUS]); // starts us off with a tandemaus + await game.startBattle([ Species.TANDEMAUS ]); // starts us off with a tandemaus const playerPokemon = game.scene.getPlayerPokemon()!; playerPokemon.level = 25; // tandemaus evolves at level 25 vi.spyOn(Utils, "randSeedInt").mockReturnValue(0); // setting the random generator to be 0 to force a three family maushold diff --git a/src/test/field/pokemon.test.ts b/src/test/field/pokemon.test.ts index 225f302ff0c..aeaecab5874 100644 --- a/src/test/field/pokemon.test.ts +++ b/src/test/field/pokemon.test.ts @@ -24,7 +24,7 @@ describe("Spec - Pokemon", () => { }); it("should not crash when trying to set status of undefined", async () => { - await game.classicMode.runToSummon([Species.ABRA]); + await game.classicMode.runToSummon([ Species.ABRA ]); const pkm = game.scene.getPlayerPokemon()!; expect(pkm).toBeDefined(); @@ -37,7 +37,7 @@ describe("Spec - Pokemon", () => { beforeEach(async () => { game.override.enemySpecies(Species.ZUBAT); - await game.classicMode.runToSummon([Species.ABRA, Species.ABRA, Species.ABRA, Species.ABRA, Species.ABRA]); // 5 Abra, only 1 slot left + await game.classicMode.runToSummon([ Species.ABRA, Species.ABRA, Species.ABRA, Species.ABRA, Species.ABRA ]); // 5 Abra, only 1 slot left scene = game.scene; }); @@ -68,7 +68,7 @@ describe("Spec - Pokemon", () => { it("should not share tms between different forms", async () => { game.override.starterForms({ [Species.ROTOM]: 4 }); - await game.classicMode.startBattle([Species.ROTOM]); + await game.classicMode.startBattle([ Species.ROTOM ]); const fanRotom = game.scene.getPlayerPokemon()!; diff --git a/src/test/final_boss.test.ts b/src/test/final_boss.test.ts index fee4dc6c8f6..de2cddff944 100644 --- a/src/test/final_boss.test.ts +++ b/src/test/final_boss.test.ts @@ -38,7 +38,7 @@ describe("Final Boss", () => { }); it("should spawn Eternatus on wave 200 in END biome", async () => { - await game.runToFinalBossEncounter([Species.BIDOOF], GameModes.CLASSIC); + await game.runToFinalBossEncounter([ Species.BIDOOF ], GameModes.CLASSIC); expect(game.scene.currentBattle.waveIndex).toBe(FinalWave.Classic); expect(game.scene.arena.biomeType).toBe(Biome.END); @@ -47,7 +47,7 @@ describe("Final Boss", () => { it("should NOT spawn Eternatus before wave 200 in END biome", async () => { game.override.startingWave(FinalWave.Classic - 1); - await game.runToFinalBossEncounter([Species.BIDOOF], GameModes.CLASSIC); + await game.runToFinalBossEncounter([ Species.BIDOOF ], GameModes.CLASSIC); expect(game.scene.currentBattle.waveIndex).not.toBe(FinalWave.Classic); expect(game.scene.arena.biomeType).toBe(Biome.END); @@ -56,7 +56,7 @@ describe("Final Boss", () => { it("should NOT spawn Eternatus outside of END biome", async () => { game.override.startingBiome(Biome.FOREST); - await game.runToFinalBossEncounter([Species.BIDOOF], GameModes.CLASSIC); + await game.runToFinalBossEncounter([ Species.BIDOOF ], GameModes.CLASSIC); expect(game.scene.currentBattle.waveIndex).toBe(FinalWave.Classic); expect(game.scene.arena.biomeType).not.toBe(Biome.END); @@ -64,7 +64,7 @@ describe("Final Boss", () => { }); it("should not have passive enabled on Eternatus", async () => { - await game.runToFinalBossEncounter([Species.BIDOOF], GameModes.CLASSIC); + await game.runToFinalBossEncounter([ Species.BIDOOF ], GameModes.CLASSIC); const eternatus = game.scene.getEnemyPokemon()!; expect(eternatus.species.speciesId).toBe(Species.ETERNATUS); @@ -72,7 +72,7 @@ describe("Final Boss", () => { }); it("should change form on direct hit down to last boss fragment", async () => { - await game.runToFinalBossEncounter([Species.KYUREM], GameModes.CLASSIC); + await game.runToFinalBossEncounter([ Species.KYUREM ], GameModes.CLASSIC); await game.phaseInterceptor.to("CommandPhase"); // Eternatus phase 1 @@ -101,7 +101,7 @@ describe("Final Boss", () => { it("should change form on status damage down to last boss fragment", async () => { game.override.ability(Abilities.NO_GUARD); - await game.runToFinalBossEncounter([Species.BIDOOF], GameModes.CLASSIC); + await game.runToFinalBossEncounter([ Species.BIDOOF ], GameModes.CLASSIC); await game.phaseInterceptor.to("CommandPhase"); // Eternatus phase 1 diff --git a/src/test/internals.test.ts b/src/test/internals.test.ts index 3c76b40e901..ce2cd55dbc6 100644 --- a/src/test/internals.test.ts +++ b/src/test/internals.test.ts @@ -23,7 +23,7 @@ describe("Internals", () => { }); it("should provide Eevee with 3 defined abilities", async () => { - await game.classicMode.runToSummon([Species.EEVEE]); + await game.classicMode.runToSummon([ Species.EEVEE ]); const eevee = game.scene.getPlayerPokemon()!; expect(eevee.getSpeciesForm().getAbilityCount()).toBe(3); @@ -34,7 +34,7 @@ describe("Internals", () => { }); it("should set Eeeve abilityIndex between 0-2", async () => { - await game.classicMode.runToSummon([Species.EEVEE]); + await game.classicMode.runToSummon([ Species.EEVEE ]); const eevee = game.scene.getPlayerPokemon()!; expect(eevee.abilityIndex).toBeGreaterThanOrEqual(0); diff --git a/src/test/items/exp_booster.test.ts b/src/test/items/exp_booster.test.ts index 9a7464e4866..36107329706 100644 --- a/src/test/items/exp_booster.test.ts +++ b/src/test/items/exp_booster.test.ts @@ -28,7 +28,7 @@ describe("EXP Modifier Items", () => { }); it("EXP booster items stack multiplicatively", async() => { - game.override.startingHeldItems([{name: "LUCKY_EGG", count: 3}, {name: "GOLDEN_EGG"}]); + game.override.startingHeldItems([{ name: "LUCKY_EGG", count: 3 }, { name: "GOLDEN_EGG" }]); await game.startBattle(); const partyMember = game.scene.getPlayerPokemon()!; diff --git a/src/test/items/grip_claw.test.ts b/src/test/items/grip_claw.test.ts index 29d39cabc3e..2909549af87 100644 --- a/src/test/items/grip_claw.test.ts +++ b/src/test/items/grip_claw.test.ts @@ -1,16 +1,14 @@ import { BattlerIndex } from "#app/battle"; -import { allMoves } from "#app/data/move"; -import { Abilities } from "#app/enums/abilities"; -import { BerryType } from "#app/enums/berry-type"; -import { Moves } from "#app/enums/moves"; -import { Species } from "#app/enums/species"; -import { MoveEndPhase } from "#app/phases/move-end-phase"; +import Pokemon from "#app/field/pokemon"; +import { ContactHeldItemTransferChanceModifier } from "#app/modifier/modifier"; +import { Abilities } from "#enums/abilities"; +import { BerryType } from "#enums/berry-type"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -// 20 seconds - describe("Items - Grip Claw", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -30,39 +28,85 @@ describe("Items - Grip Claw", () => { game.override .battleType("double") - .moveset([Moves.POPULATION_BOMB, Moves.SPLASH]) + .moveset([ Moves.TACKLE, Moves.SPLASH, Moves.ATTRACT ]) .startingHeldItems([ - { name: "GRIP_CLAW", count: 5 }, // TODO: Find a way to mock the steal chance of grip claw - { name: "MULTI_LENS", count: 3 }, + { name: "GRIP_CLAW", count: 1 }, ]) .enemySpecies(Species.SNORLAX) - .ability(Abilities.KLUTZ) + .enemyAbility(Abilities.UNNERVE) + .ability(Abilities.UNNERVE) .enemyMoveset(Moves.SPLASH) .enemyHeldItems([ { name: "BERRY", type: BerryType.SITRUS, count: 2 }, { name: "BERRY", type: BerryType.LUM, count: 2 }, ]) - .startingLevel(100) .enemyLevel(100); - vi.spyOn(allMoves[Moves.POPULATION_BOMB], "accuracy", "get").mockReturnValue(100); }); - it( - "should only steal items from the attack target", - async () => { - await game.startBattle([Species.PANSEAR, Species.ROWLET]); + it("should steal items on contact and only from the attack target", async () => { + await game.classicMode.startBattle([ Species.FEEBAS, Species.MILOTIC ]); - const enemyPokemon = game.scene.getEnemyField(); + const [ playerPokemon, ] = game.scene.getPlayerField(); - const enemyHeldItemCt = enemyPokemon.map(p => p.getHeldItems.length); + const gripClaw = playerPokemon.getHeldItems()[0] as ContactHeldItemTransferChanceModifier; + vi.spyOn(gripClaw, "chance", "get").mockReturnValue(100); - game.move.select(Moves.POPULATION_BOMB, 0, BattlerIndex.ENEMY); - game.move.select(Moves.SPLASH, 1); + const enemyPokemon = game.scene.getEnemyField(); - await game.phaseInterceptor.to(MoveEndPhase, false); + const playerHeldItemCount = getHeldItemCount(playerPokemon); + const enemy1HeldItemCount = getHeldItemCount(enemyPokemon[0]); + const enemy2HeldItemCount = getHeldItemCount(enemyPokemon[1]); + expect(enemy2HeldItemCount).toBeGreaterThan(0); - expect(enemyPokemon[1].getHeldItems.length).toBe(enemyHeldItemCt[1]); - } - ); + game.move.select(Moves.TACKLE, 0, BattlerIndex.ENEMY_2); + game.move.select(Moves.SPLASH, 1); + + await game.phaseInterceptor.to("BerryPhase", false); + + const playerHeldItemCountAfter = getHeldItemCount(playerPokemon); + const enemy1HeldItemCountsAfter = getHeldItemCount(enemyPokemon[0]); + const enemy2HeldItemCountsAfter = getHeldItemCount(enemyPokemon[1]); + + expect(playerHeldItemCountAfter).toBe(playerHeldItemCount + 1); + expect(enemy1HeldItemCountsAfter).toBe(enemy1HeldItemCount); + expect(enemy2HeldItemCountsAfter).toBe(enemy2HeldItemCount - 1); + }); + + it("should not steal items when using a targetted, non attack move", async () => { + await game.classicMode.startBattle([ Species.FEEBAS, Species.MILOTIC ]); + + const [ playerPokemon, ] = game.scene.getPlayerField(); + + const gripClaw = playerPokemon.getHeldItems()[0] as ContactHeldItemTransferChanceModifier; + vi.spyOn(gripClaw, "chance", "get").mockReturnValue(100); + + const enemyPokemon = game.scene.getEnemyField(); + + const playerHeldItemCount = getHeldItemCount(playerPokemon); + const enemy1HeldItemCount = getHeldItemCount(enemyPokemon[0]); + const enemy2HeldItemCount = getHeldItemCount(enemyPokemon[1]); + expect(enemy2HeldItemCount).toBeGreaterThan(0); + + game.move.select(Moves.ATTRACT, 0, BattlerIndex.ENEMY_2); + game.move.select(Moves.SPLASH, 1); + + await game.phaseInterceptor.to("BerryPhase", false); + + const playerHeldItemCountAfter = getHeldItemCount(playerPokemon); + const enemy1HeldItemCountsAfter = getHeldItemCount(enemyPokemon[0]); + const enemy2HeldItemCountsAfter = getHeldItemCount(enemyPokemon[1]); + + expect(playerHeldItemCountAfter).toBe(playerHeldItemCount); + expect(enemy1HeldItemCountsAfter).toBe(enemy1HeldItemCount); + expect(enemy2HeldItemCountsAfter).toBe(enemy2HeldItemCount); + }); }); + +/* + * Gets the total number of items a Pokemon holds + */ +function getHeldItemCount(pokemon: Pokemon) { + return pokemon.getHeldItems().reduce((currentTotal, item) => currentTotal + item.getStackCount(), 0); +} + diff --git a/src/test/items/leek.test.ts b/src/test/items/leek.test.ts index af20516ef83..e27462a9265 100644 --- a/src/test/items/leek.test.ts +++ b/src/test/items/leek.test.ts @@ -25,7 +25,7 @@ describe("Items - Leek", () => { game.override .enemySpecies(Species.MAGIKARP) - .enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]) + .enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]) .startingHeldItems([{ name: "LEEK" }]) .moveset([ Moves.TACKLE ]) .disableCrits() @@ -82,7 +82,7 @@ describe("Items - Leek", () => { it("should raise CRIT stage by 2 when held by FARFETCHD line fused with Pokemon", async () => { // Randomly choose from the Farfetch'd line - const species = [Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD]; + const species = [ Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD ]; await game.startBattle([ species[Utils.randInt(species.length)], @@ -113,7 +113,7 @@ describe("Items - Leek", () => { it("should raise CRIT stage by 2 when held by Pokemon fused with FARFETCHD line", async () => { // Randomly choose from the Farfetch'd line - const species = [Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD]; + const species = [ Species.FARFETCHD, Species.GALAR_FARFETCHD, Species.SIRFETCHD ]; await game.startBattle([ Species.PIKACHU, diff --git a/src/test/items/leftovers.test.ts b/src/test/items/leftovers.test.ts index 8e548542436..cfbf7c2f734 100644 --- a/src/test/items/leftovers.test.ts +++ b/src/test/items/leftovers.test.ts @@ -27,15 +27,15 @@ describe("Items - Leftovers", () => { game.override.battleType("single"); game.override.startingLevel(2000); game.override.ability(Abilities.UNNERVE); - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); game.override.enemySpecies(Species.SHUCKLE); game.override.enemyAbility(Abilities.UNNERVE); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); game.override.startingHeldItems([{ name: "LEFTOVERS", count: 1 }]); }); it("leftovers works", async () => { - await game.startBattle([Species.ARCANINE]); + await game.startBattle([ Species.ARCANINE ]); // Make sure leftovers are there expect(game.scene.modifiers[0].type.id).toBe("LEFTOVERS"); diff --git a/src/test/items/light_ball.test.ts b/src/test/items/light_ball.test.ts index 673348e7b7a..78375487f3b 100644 --- a/src/test/items/light_ball.test.ts +++ b/src/test/items/light_ball.test.ts @@ -83,7 +83,7 @@ describe("Items - Light Ball", () => { expect(spAtkValue.value / spAtkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["LIGHT_BALL"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue); @@ -122,7 +122,7 @@ describe("Items - Light Ball", () => { expect(spAtkValue.value / spAtkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["LIGHT_BALL"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue); @@ -161,7 +161,7 @@ describe("Items - Light Ball", () => { expect(spAtkValue.value / spAtkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["LIGHT_BALL"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue); @@ -189,7 +189,7 @@ describe("Items - Light Ball", () => { expect(spAtkValue.value / spAtkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["LIGHT_BALL"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "LIGHT_BALL" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPATK, spAtkValue); diff --git a/src/test/items/lock_capsule.test.ts b/src/test/items/lock_capsule.test.ts index bc4ca1cb014..0b6534b5eaf 100644 --- a/src/test/items/lock_capsule.test.ts +++ b/src/test/items/lock_capsule.test.ts @@ -1,7 +1,8 @@ import { Abilities } from "#app/enums/abilities"; import { Moves } from "#app/enums/moves"; -import { ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type"; +import { ModifierTier } from "#app/modifier/modifier-tier"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; +import { Mode } from "#app/ui/ui"; import GameManager from "#test/utils/gameManager"; import Phase from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -26,21 +27,22 @@ describe("Items - Lock Capsule", () => { game.override .battleType("single") .startingLevel(200) - .moveset([Moves.SURF]) + .moveset([ Moves.SURF ]) .enemyAbility(Abilities.BALL_FETCH) .startingModifier([{ name: "LOCK_CAPSULE" }]); }); it("doesn't set the cost of common tier items to 0", async () => { - await game.startBattle(); + await game.classicMode.startBattle(); + game.scene.overridePhase(new SelectModifierPhase(game.scene, 0, undefined, { guaranteedModifierTiers: [ ModifierTier.COMMON, ModifierTier.COMMON, ModifierTier.COMMON ], fillRemaining: false })); - game.move.select(Moves.SURF); - await game.phaseInterceptor.to(SelectModifierPhase, false); + game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => { + const selectModifierPhase = game.scene.getCurrentPhase() as SelectModifierPhase; + const rerollCost = selectModifierPhase.getRerollCost(true); + expect(rerollCost).toBe(150); + }); - const rewards = game.scene.getCurrentPhase() as SelectModifierPhase; - const potion = new ModifierTypeOption(modifierTypes.POTION(), 0, 40); // Common tier item - const rerollCost = rewards.getRerollCost([potion, potion, potion], true); - - expect(rerollCost).toBe(150); + game.doSelectModifier(); + await game.phaseInterceptor.to("SelectModifierPhase"); }, 20000); }); diff --git a/src/test/items/metal_powder.test.ts b/src/test/items/metal_powder.test.ts index 0206fd1f471..c577182f350 100644 --- a/src/test/items/metal_powder.test.ts +++ b/src/test/items/metal_powder.test.ts @@ -79,7 +79,7 @@ describe("Items - Metal Powder", () => { expect(defValue.value / defStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["METAL_POWDER"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue); expect(defValue.value / defStat).toBe(2); @@ -112,7 +112,7 @@ describe("Items - Metal Powder", () => { expect(defValue.value / defStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["METAL_POWDER"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue); expect(defValue.value / defStat).toBe(2); @@ -145,7 +145,7 @@ describe("Items - Metal Powder", () => { expect(defValue.value / defStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["METAL_POWDER"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue); expect(defValue.value / defStat).toBe(2); @@ -167,7 +167,7 @@ describe("Items - Metal Powder", () => { expect(defValue.value / defStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["METAL_POWDER"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "METAL_POWDER" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.DEF, defValue); expect(defValue.value / defStat).toBe(1); diff --git a/src/test/items/quick_powder.test.ts b/src/test/items/quick_powder.test.ts index 344b772feb4..4eb6f6fb164 100644 --- a/src/test/items/quick_powder.test.ts +++ b/src/test/items/quick_powder.test.ts @@ -79,7 +79,7 @@ describe("Items - Quick Powder", () => { expect(spdValue.value / spdStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["QUICK_POWDER"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue); expect(spdValue.value / spdStat).toBe(2); @@ -112,7 +112,7 @@ describe("Items - Quick Powder", () => { expect(spdValue.value / spdStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["QUICK_POWDER"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue); expect(spdValue.value / spdStat).toBe(2); @@ -145,7 +145,7 @@ describe("Items - Quick Powder", () => { expect(spdValue.value / spdStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["QUICK_POWDER"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue); expect(spdValue.value / spdStat).toBe(2); @@ -167,7 +167,7 @@ describe("Items - Quick Powder", () => { expect(spdValue.value / spdStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["QUICK_POWDER"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "QUICK_POWDER" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.SPD, spdValue); expect(spdValue.value / spdStat).toBe(1); diff --git a/src/test/items/thick_club.test.ts b/src/test/items/thick_club.test.ts index bcb6b371264..74158089c77 100644 --- a/src/test/items/thick_club.test.ts +++ b/src/test/items/thick_club.test.ts @@ -79,7 +79,7 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["THICK_CLUB"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(2); @@ -101,7 +101,7 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["THICK_CLUB"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(2); @@ -123,7 +123,7 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["THICK_CLUB"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(2); @@ -160,7 +160,7 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["THICK_CLUB"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(2); @@ -197,7 +197,7 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["THICK_CLUB"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(2); @@ -219,7 +219,7 @@ describe("Items - Thick Club", () => { expect(atkValue.value / atkStat).toBe(1); // Giving Eviolite to party member and testing if it applies - partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], ["THICK_CLUB"])!.newModifier(partyMember), true); + partyMember.scene.addModifier(modifierTypes.SPECIES_STAT_BOOSTER().generateType([], [ "THICK_CLUB" ])!.newModifier(partyMember), true); partyMember.scene.applyModifiers(SpeciesStatBoosterModifier, true, partyMember, Stat.ATK, atkValue); expect(atkValue.value / atkStat).toBe(1); diff --git a/src/test/items/toxic_orb.test.ts b/src/test/items/toxic_orb.test.ts index 66806083f6f..63c7b6245f5 100644 --- a/src/test/items/toxic_orb.test.ts +++ b/src/test/items/toxic_orb.test.ts @@ -1,15 +1,13 @@ import { StatusEffect } from "#app/data/status-effect"; -import { EnemyCommandPhase } from "#app/phases/enemy-command-phase"; -import { MessagePhase } from "#app/phases/message-phase"; -import { TurnEndPhase } from "#app/phases/turn-end-phase"; -import i18next, { initI18n } from "#app/plugins/i18n"; +import i18next from "#app/plugins/i18n"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +const TIMEOUT = 20 * 1000; describe("Items - Toxic orb", () => { let phaserGame: Phaser.Game; @@ -27,41 +25,36 @@ describe("Items - Toxic orb", () => { beforeEach(() => { game = new GameManager(phaserGame); - const moveToUse = Moves.GROWTH; - const oppMoveToUse = Moves.TACKLE; - game.override.battleType("single"); - game.override.enemySpecies(Species.RATTATA); - game.override.ability(Abilities.INSOMNIA); - game.override.enemyAbility(Abilities.INSOMNIA); - game.override.startingLevel(2000); - game.override.moveset([moveToUse]); - game.override.enemyMoveset([oppMoveToUse, oppMoveToUse, oppMoveToUse, oppMoveToUse]); - game.override.startingHeldItems([{ - name: "TOXIC_ORB", - }]); + game.override + .battleType("single") + .enemySpecies(Species.RATTATA) + .ability(Abilities.BALL_FETCH) + .enemyAbility(Abilities.BALL_FETCH) + .moveset([ Moves.SPLASH ]) + .enemyMoveset(Moves.SPLASH) + .startingHeldItems([{ + name: "TOXIC_ORB", + }]); + + vi.spyOn(i18next, "t"); }); - it("TOXIC ORB", async () => { - initI18n(); - i18next.changeLanguage("en"); - const moveToUse = Moves.GROWTH; - await game.startBattle([ - Species.MIGHTYENA, - Species.MIGHTYENA, - ]); - expect(game.scene.modifiers[0].type.id).toBe("TOXIC_ORB"); + it("badly poisons the holder", async () => { + await game.classicMode.startBattle([ Species.MIGHTYENA ]); - game.move.select(moveToUse); + const player = game.scene.getPlayerField()[0]; - // will run the 13 phase from enemyCommandPhase to TurnEndPhase - await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase); + game.move.select(Moves.SPLASH); + + await game.phaseInterceptor.to("TurnEndPhase"); // Toxic orb should trigger here - await game.phaseInterceptor.run(MessagePhase); - const message = game.textInterceptor.getLatestMessage(); - expect(message).toContain("statusEffect:toxic.obtainSource"); - await game.phaseInterceptor.run(MessagePhase); - const message2 = game.textInterceptor.getLatestMessage(); - expect(message2).toBe("statusEffect:toxic.activation"); - expect(game.scene.getParty()[0].status!.effect).toBe(StatusEffect.TOXIC); - }, 20000); + await game.phaseInterceptor.run("MessagePhase"); + expect(i18next.t).toHaveBeenCalledWith("statusEffect:toxic.obtainSource", expect.anything()); + + await game.toNextTurn(); + + expect(player.status?.effect).toBe(StatusEffect.TOXIC); + // Damage should not have ticked yet. + expect(player.status?.turnCount).toBe(0); + }, TIMEOUT); }); diff --git a/src/test/misc.test.ts b/src/test/misc.test.ts index 1052a282a64..3335c4c5523 100644 --- a/src/test/misc.test.ts +++ b/src/test/misc.test.ts @@ -64,7 +64,7 @@ describe("Test misc", () => { it("testing wait phase queue", async () => { const fakeScene = { - phaseQueue: [1, 2, 3] // Initially not empty + phaseQueue: [ 1, 2, 3 ] // Initially not empty }; setTimeout(() => { fakeScene.phaseQueue = []; diff --git a/src/test/moves/after_you.test.ts b/src/test/moves/after_you.test.ts index 025b4804bf1..99f383194aa 100644 --- a/src/test/moves/after_you.test.ts +++ b/src/test/moves/after_you.test.ts @@ -9,7 +9,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Moves - After You", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -33,11 +32,11 @@ describe("Moves - After You", () => { .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH) .ability(Abilities.BALL_FETCH) - .moveset([Moves.AFTER_YOU, Moves.SPLASH]); + .moveset([ Moves.AFTER_YOU, Moves.SPLASH ]); }); it("makes the target move immediately after the user", async () => { - await game.classicMode.startBattle([Species.REGIELEKI, Species.SHUCKLE]); + await game.classicMode.startBattle([ Species.REGIELEKI, Species.SHUCKLE ]); game.move.select(Moves.AFTER_YOU, 0, BattlerIndex.PLAYER_2); game.move.select(Moves.SPLASH, 1); @@ -51,7 +50,7 @@ describe("Moves - After You", () => { it("fails if target already moved", async () => { game.override.enemySpecies(Species.SHUCKLE); - await game.classicMode.startBattle([Species.REGIELEKI, Species.PIKACHU]); + await game.classicMode.startBattle([ Species.REGIELEKI, Species.PIKACHU ]); game.move.select(Moves.SPLASH); game.move.select(Moves.AFTER_YOU, 1, BattlerIndex.PLAYER); diff --git a/src/test/moves/alluring_voice.test.ts b/src/test/moves/alluring_voice.test.ts index 3e86b46aa69..2980f102735 100644 --- a/src/test/moves/alluring_voice.test.ts +++ b/src/test/moves/alluring_voice.test.ts @@ -9,7 +9,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Moves - Alluring Voice", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -31,12 +30,12 @@ describe("Moves - Alluring Voice", () => { .disableCrits() .enemySpecies(Species.MAGIKARP) .enemyAbility(Abilities.ICE_SCALES) - .enemyMoveset([Moves.HOWL]) + .enemyMoveset([ Moves.HOWL ]) .startingLevel(10) .enemyLevel(10) .starterSpecies(Species.FEEBAS) .ability(Abilities.BALL_FETCH) - .moveset([Moves.ALLURING_VOICE]); + .moveset([ Moves.ALLURING_VOICE ]); }); @@ -46,7 +45,7 @@ describe("Moves - Alluring Voice", () => { const enemy = game.scene.getEnemyPokemon()!; game.move.select(Moves.ALLURING_VOICE); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to(BerryPhase); expect(enemy.getTag(BattlerTagType.CONFUSED)?.tagType).toBe("CONFUSED"); diff --git a/src/test/moves/aromatherapy.test.ts b/src/test/moves/aromatherapy.test.ts index acc2e9c5fae..f547ed0e54c 100644 --- a/src/test/moves/aromatherapy.test.ts +++ b/src/test/moves/aromatherapy.test.ts @@ -24,7 +24,7 @@ describe("Moves - Aromatherapy", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.AROMATHERAPY, Moves.SPLASH]) + .moveset([ Moves.AROMATHERAPY, Moves.SPLASH ]) .statusEffect(StatusEffect.BURN) .battleType("double") .enemyAbility(Abilities.BALL_FETCH) @@ -32,8 +32,8 @@ describe("Moves - Aromatherapy", () => { }); it("should cure status effect of the user, its ally, and all party pokemon", async () => { - await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA, Species.RATTATA]); - const [leftPlayer, rightPlayer, partyPokemon] = game.scene.getParty(); + await game.classicMode.startBattle([ Species.RATTATA, Species.RATTATA, Species.RATTATA ]); + const [ leftPlayer, rightPlayer, partyPokemon ] = game.scene.getParty(); vi.spyOn(leftPlayer, "resetStatus"); vi.spyOn(rightPlayer, "resetStatus"); @@ -55,8 +55,8 @@ describe("Moves - Aromatherapy", () => { it("should not cure status effect of the target/target's allies", async () => { game.override.enemyStatusEffect(StatusEffect.BURN); - await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA]); - const [leftOpp, rightOpp] = game.scene.getEnemyField(); + await game.classicMode.startBattle([ Species.RATTATA, Species.RATTATA ]); + const [ leftOpp, rightOpp ] = game.scene.getEnemyField(); vi.spyOn(leftOpp, "resetStatus"); vi.spyOn(rightOpp, "resetStatus"); @@ -78,8 +78,8 @@ describe("Moves - Aromatherapy", () => { it("should not cure status effect of allies ON FIELD with Sap Sipper, should still cure allies in party", async () => { game.override.ability(Abilities.SAP_SIPPER); - await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA, Species.RATTATA]); - const [leftPlayer, rightPlayer, partyPokemon] = game.scene.getParty(); + await game.classicMode.startBattle([ Species.RATTATA, Species.RATTATA, Species.RATTATA ]); + const [ leftPlayer, rightPlayer, partyPokemon ] = game.scene.getParty(); vi.spyOn(leftPlayer, "resetStatus"); vi.spyOn(rightPlayer, "resetStatus"); diff --git a/src/test/moves/astonish.test.ts b/src/test/moves/astonish.test.ts index 694ad85803b..d94e50fc9f9 100644 --- a/src/test/moves/astonish.test.ts +++ b/src/test/moves/astonish.test.ts @@ -12,7 +12,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; - describe("Moves - Astonish", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -30,10 +29,10 @@ describe("Moves - Astonish", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("single"); - game.override.moveset([Moves.ASTONISH, Moves.SPLASH]); + game.override.moveset([ Moves.ASTONISH, Moves.SPLASH ]); game.override.enemySpecies(Species.BLASTOISE); game.override.enemyAbility(Abilities.INSOMNIA); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); game.override.startingLevel(100); game.override.enemyLevel(100); @@ -43,7 +42,7 @@ describe("Moves - Astonish", () => { test( "move effect should cancel the target's move on the turn it applies", async () => { - await game.startBattle([Species.MEOWSCARADA]); + await game.startBattle([ Species.MEOWSCARADA ]); const leadPokemon = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/aurora_veil.test.ts b/src/test/moves/aurora_veil.test.ts index fec280debf4..243ba3a3269 100644 --- a/src/test/moves/aurora_veil.test.ts +++ b/src/test/moves/aurora_veil.test.ts @@ -33,17 +33,17 @@ describe("Moves - Aurora Veil", () => { game = new GameManager(phaserGame); game.override.battleType("single"); game.override.ability(Abilities.NONE); - game.override.moveset([Moves.ABSORB, Moves.ROCK_SLIDE, Moves.TACKLE]); + game.override.moveset([ Moves.ABSORB, Moves.ROCK_SLIDE, Moves.TACKLE ]); game.override.enemyLevel(100); game.override.enemySpecies(Species.MAGIKARP); - game.override.enemyMoveset([Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL]); + game.override.enemyMoveset([ Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL, Moves.AURORA_VEIL ]); game.override.disableCrits(); game.override.weather(WeatherType.HAIL); }); it("reduces damage of physical attacks by half in a single battle", async () => { const moveToUse = Moves.TACKLE; - await game.startBattle([Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE ]); game.move.select(moveToUse); @@ -57,7 +57,7 @@ describe("Moves - Aurora Veil", () => { game.override.battleType("double"); const moveToUse = Moves.ROCK_SLIDE; - await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE, Species.SHUCKLE ]); game.move.select(moveToUse); game.move.select(moveToUse, 1); @@ -70,7 +70,7 @@ describe("Moves - Aurora Veil", () => { it("reduces damage of special attacks by half in a single battle", async () => { const moveToUse = Moves.ABSORB; - await game.startBattle([Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE ]); game.move.select(moveToUse); @@ -85,7 +85,7 @@ describe("Moves - Aurora Veil", () => { game.override.battleType("double"); const moveToUse = Moves.DAZZLING_GLEAM; - await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE, Species.SHUCKLE ]); game.move.select(moveToUse); game.move.select(moveToUse, 1); @@ -111,7 +111,7 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) = const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; if (defender.scene.arena.getTagOnSide(ArenaTagType.AURORA_VEIL, side)) { - defender.scene.arena.applyTagsForSide(ArenaTagType.AURORA_VEIL, side, move.category, defender.scene.currentBattle.double, multiplierHolder); + defender.scene.arena.applyTagsForSide(ArenaTagType.AURORA_VEIL, side, false, move.category, multiplierHolder); } return move.power * multiplierHolder.value; diff --git a/src/test/moves/autotomize.test.ts b/src/test/moves/autotomize.test.ts index 329b92b38fe..e15642b7ce5 100644 --- a/src/test/moves/autotomize.test.ts +++ b/src/test/moves/autotomize.test.ts @@ -23,7 +23,7 @@ describe("Moves - Autotomize", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.AUTOTOMIZE, Moves.KINGS_SHIELD, Moves.FALSE_SWIPE]) + .moveset([ Moves.AUTOTOMIZE, Moves.KINGS_SHIELD, Moves.FALSE_SWIPE ]) .battleType("single") .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH); @@ -35,7 +35,7 @@ describe("Moves - Autotomize", () => { const twoAutotomizeDracozoltWeight = 0.1; const threeAutotomizeDracozoltWeight = 0.1; - await game.classicMode.startBattle([Species.DRACOZOLT]); + await game.classicMode.startBattle([ Species.DRACOZOLT ]); const playerPokemon = game.scene.getPlayerPokemon()!; expect(playerPokemon.getWeight()).toBe(baseDracozoltWeight); game.move.select(Moves.AUTOTOMIZE); @@ -56,7 +56,7 @@ describe("Moves - Autotomize", () => { const baseAegislashWeight = 53; const autotomizeAegislashWeight = 0.1; - await game.classicMode.startBattle([Species.AEGISLASH]); + await game.classicMode.startBattle([ Species.AEGISLASH ]); const playerPokemon = game.scene.getPlayerPokemon()!; expect(playerPokemon.getWeight()).toBe(baseAegislashWeight); @@ -88,7 +88,7 @@ describe("Moves - Autotomize", () => { const baseLightGroudonWeight = 475; const autotomizeLightGroudonWeight = 425; game.override.ability(Abilities.LIGHT_METAL); - await game.classicMode.startBattle([Species.GROUDON]); + await game.classicMode.startBattle([ Species.GROUDON ]); const playerPokemon = game.scene.getPlayerPokemon()!; expect(playerPokemon.getWeight()).toBe(baseLightGroudonWeight); game.move.select(Moves.AUTOTOMIZE); diff --git a/src/test/moves/baddy_bad.test.ts b/src/test/moves/baddy_bad.test.ts index 87a7e9e049d..1be25704393 100644 --- a/src/test/moves/baddy_bad.test.ts +++ b/src/test/moves/baddy_bad.test.ts @@ -21,7 +21,7 @@ describe("Moves - Baddy Bad", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.SPLASH]) + .moveset([ Moves.SPLASH ]) .battleType("single") .enemySpecies(Species.MAGIKARP) .enemyAbility(Abilities.BALL_FETCH) @@ -31,7 +31,7 @@ describe("Moves - Baddy Bad", () => { it("should not activate Reflect if the move fails due to Protect", async () => { game.override.enemyMoveset(Moves.PROTECT); - await game.classicMode.startBattle([Species.FEEBAS]); + await game.classicMode.startBattle([ Species.FEEBAS ]); game.move.select(Moves.BADDY_BAD); await game.phaseInterceptor.to("BerryPhase"); diff --git a/src/test/moves/baneful_bunker.test.ts b/src/test/moves/baneful_bunker.test.ts index 5f63e3b4313..a0fc0f21ee2 100644 --- a/src/test/moves/baneful_bunker.test.ts +++ b/src/test/moves/baneful_bunker.test.ts @@ -8,7 +8,6 @@ import { BattlerIndex } from "#app/battle"; import { StatusEffect } from "#app/enums/status-effect"; - describe("Moves - Baneful Bunker", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -40,13 +39,13 @@ describe("Moves - Baneful Bunker", () => { test( "should protect the user and poison attackers that make contact", async () => { - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.SLASH); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); expect(leadPokemon.status?.effect === StatusEffect.POISON).toBeTruthy(); @@ -55,13 +54,13 @@ describe("Moves - Baneful Bunker", () => { test( "should protect the user and poison attackers that make contact, regardless of accuracy checks", async () => { - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.SLASH); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("MoveEffectPhase"); await game.move.forceMiss(); @@ -75,13 +74,13 @@ describe("Moves - Baneful Bunker", () => { "should not poison attackers that don't make contact", async () => { game.override.moveset(Moves.FLASH_CANNON); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.FLASH_CANNON); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("MoveEffectPhase"); await game.move.forceMiss(); diff --git a/src/test/moves/baton_pass.test.ts b/src/test/moves/baton_pass.test.ts index 5643efceae2..5e6e4be21ba 100644 --- a/src/test/moves/baton_pass.test.ts +++ b/src/test/moves/baton_pass.test.ts @@ -28,7 +28,7 @@ describe("Moves - Baton Pass", () => { .battleType("single") .enemySpecies(Species.MAGIKARP) .enemyAbility(Abilities.BALL_FETCH) - .moveset([Moves.BATON_PASS, Moves.NASTY_PLOT, Moves.SPLASH]) + .moveset([ Moves.BATON_PASS, Moves.NASTY_PLOT, Moves.SPLASH ]) .ability(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH) .disableCrits(); @@ -36,7 +36,7 @@ describe("Moves - Baton Pass", () => { it("transfers all stat stages when player uses it", async() => { // arrange - await game.classicMode.startBattle([Species.RAICHU, Species.SHUCKLE]); + await game.classicMode.startBattle([ Species.RAICHU, Species.SHUCKLE ]); // round 1 - buff game.move.select(Moves.NASTY_PLOT); @@ -61,8 +61,8 @@ describe("Moves - Baton Pass", () => { // arrange game.override .startingWave(5) - .enemyMoveset(new Array(4).fill([Moves.NASTY_PLOT])); - await game.classicMode.startBattle([Species.RAICHU, Species.SHUCKLE]); + .enemyMoveset(new Array(4).fill([ Moves.NASTY_PLOT ])); + await game.classicMode.startBattle([ Species.RAICHU, Species.SHUCKLE ]); // round 1 - ai buffs game.move.select(Moves.SPLASH); @@ -70,7 +70,7 @@ describe("Moves - Baton Pass", () => { // round 2 - baton pass game.scene.getEnemyPokemon()!.hp = 100; - game.override.enemyMoveset([Moves.BATON_PASS]); + game.override.enemyMoveset([ Moves.BATON_PASS ]); // Force moveset to update mid-battle // TODO: replace with enemy ai control function when it's added game.scene.getEnemyParty()[0].getMoveset(); @@ -92,13 +92,13 @@ describe("Moves - Baton Pass", () => { }, 20000); it("doesn't transfer effects that aren't transferrable", async() => { - game.override.enemyMoveset([Moves.SALT_CURE]); - await game.classicMode.startBattle([Species.PIKACHU, Species.FEEBAS]); + game.override.enemyMoveset([ Moves.SALT_CURE ]); + await game.classicMode.startBattle([ Species.PIKACHU, Species.FEEBAS ]); - const [player1, player2] = game.scene.getParty(); + const [ player1, player2 ] = game.scene.getParty(); game.move.select(Moves.BATON_PASS); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(player1.findTag((t) => t.tagType === BattlerTagType.SALT_CURED)).toBeTruthy(); game.doSelectPartyPokemon(1); diff --git a/src/test/moves/beak_blast.test.ts b/src/test/moves/beak_blast.test.ts index 3f4fe1d1d11..0c1e7bbeed9 100644 --- a/src/test/moves/beak_blast.test.ts +++ b/src/test/moves/beak_blast.test.ts @@ -11,7 +11,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Moves - Beak Blast", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -31,10 +30,10 @@ describe("Moves - Beak Blast", () => { game.override .battleType("single") .ability(Abilities.UNNERVE) - .moveset([Moves.BEAK_BLAST]) + .moveset([ Moves.BEAK_BLAST ]) .enemySpecies(Species.SNORLAX) .enemyAbility(Abilities.INSOMNIA) - .enemyMoveset([Moves.TACKLE]) + .enemyMoveset([ Moves.TACKLE ]) .startingLevel(100) .enemyLevel(100); }); @@ -42,7 +41,7 @@ describe("Moves - Beak Blast", () => { it( "should add a charge effect that burns attackers on contact", async () => { - await game.startBattle([Species.BLASTOISE]); + await game.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -62,7 +61,7 @@ describe("Moves - Beak Blast", () => { async () => { game.override.statusEffect(StatusEffect.SLEEP); - await game.startBattle([Species.BLASTOISE]); + await game.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -80,9 +79,9 @@ describe("Moves - Beak Blast", () => { it( "should not burn attackers that don't make contact", async () => { - game.override.enemyMoveset([Moves.WATER_GUN]); + game.override.enemyMoveset([ Moves.WATER_GUN ]); - await game.startBattle([Species.BLASTOISE]); + await game.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -102,7 +101,7 @@ describe("Moves - Beak Blast", () => { async () => { game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); - await game.startBattle([Species.BLASTOISE]); + await game.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -116,9 +115,9 @@ describe("Moves - Beak Blast", () => { it( "should be blocked by Protect", async () => { - game.override.enemyMoveset([Moves.PROTECT]); + game.override.enemyMoveset([ Moves.PROTECT ]); - await game.startBattle([Species.BLASTOISE]); + await game.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/beat_up.test.ts b/src/test/moves/beat_up.test.ts index 51ec768084c..e51ac6ea452 100644 --- a/src/test/moves/beat_up.test.ts +++ b/src/test/moves/beat_up.test.ts @@ -27,17 +27,17 @@ describe("Moves - Beat Up", () => { game.override.enemySpecies(Species.SNORLAX); game.override.enemyLevel(100); - game.override.enemyMoveset([Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH ]); game.override.enemyAbility(Abilities.INSOMNIA); game.override.startingLevel(100); - game.override.moveset([Moves.BEAT_UP]); + game.override.moveset([ Moves.BEAT_UP ]); }); it( "should hit once for each healthy player Pokemon", async () => { - await game.startBattle([Species.MAGIKARP, Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.PIKACHU, Species.EEVEE]); + await game.startBattle([ Species.MAGIKARP, Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.PIKACHU, Species.EEVEE ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -61,7 +61,7 @@ describe("Moves - Beat Up", () => { it( "should not count player Pokemon with status effects towards hit count", async () => { - await game.startBattle([Species.MAGIKARP, Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.PIKACHU, Species.EEVEE]); + await game.startBattle([ Species.MAGIKARP, Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.PIKACHU, Species.EEVEE ]); const playerPokemon = game.scene.getPlayerPokemon()!; @@ -79,7 +79,7 @@ describe("Moves - Beat Up", () => { "should hit twice for each player Pokemon if the user has Multi-Lens", async () => { game.override.startingHeldItems([{ name: "MULTI_LENS", count: 1 }]); - await game.startBattle([Species.MAGIKARP, Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.PIKACHU, Species.EEVEE]); + await game.startBattle([ Species.MAGIKARP, Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.PIKACHU, Species.EEVEE ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/belly_drum.test.ts b/src/test/moves/belly_drum.test.ts index 494272089e2..0bed1248e7e 100644 --- a/src/test/moves/belly_drum.test.ts +++ b/src/test/moves/belly_drum.test.ts @@ -35,7 +35,7 @@ describe("Moves - BELLY DRUM", () => { .enemySpecies(Species.SNORLAX) .startingLevel(100) .enemyLevel(100) - .moveset([Moves.BELLY_DRUM]) + .moveset([ Moves.BELLY_DRUM ]) .enemyMoveset(Moves.SPLASH) .enemyAbility(Abilities.BALL_FETCH); }); @@ -44,7 +44,7 @@ describe("Moves - BELLY DRUM", () => { test("raises the user's ATK stat stage to its max, at the cost of 1/2 of its maximum HP", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); @@ -59,7 +59,7 @@ describe("Moves - BELLY DRUM", () => { test("will still take effect if an uninvolved stat stage is at max", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); @@ -79,7 +79,7 @@ describe("Moves - BELLY DRUM", () => { test("fails if the pokemon's ATK stat stage is at its maximum", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -95,7 +95,7 @@ describe("Moves - BELLY DRUM", () => { test("fails if the user's health is less than 1/2", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); diff --git a/src/test/moves/burning_jealousy.test.ts b/src/test/moves/burning_jealousy.test.ts index d6ebbf30bb1..fe2735cfa96 100644 --- a/src/test/moves/burning_jealousy.test.ts +++ b/src/test/moves/burning_jealousy.test.ts @@ -9,7 +9,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; - describe("Moves - Burning Jealousy", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -31,12 +30,12 @@ describe("Moves - Burning Jealousy", () => { .disableCrits() .enemySpecies(Species.MAGIKARP) .enemyAbility(Abilities.ICE_SCALES) - .enemyMoveset([Moves.HOWL]) + .enemyMoveset([ Moves.HOWL ]) .startingLevel(10) .enemyLevel(10) .starterSpecies(Species.FEEBAS) .ability(Abilities.BALL_FETCH) - .moveset([Moves.BURNING_JEALOUSY, Moves.GROWL]); + .moveset([ Moves.BURNING_JEALOUSY, Moves.GROWL ]); }); @@ -46,7 +45,7 @@ describe("Moves - Burning Jealousy", () => { const enemy = game.scene.getEnemyPokemon()!; game.move.select(Moves.BURNING_JEALOUSY); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase"); expect(enemy.status?.effect).toBe(StatusEffect.BURN); @@ -56,13 +55,13 @@ describe("Moves - Burning Jealousy", () => { game.override .starterSpecies(0) .battleType("double"); - await game.classicMode.startBattle([Species.FEEBAS, Species.ABRA]); + await game.classicMode.startBattle([ Species.FEEBAS, Species.ABRA ]); const enemy = game.scene.getEnemyPokemon()!; game.move.select(Moves.BURNING_JEALOUSY); game.move.select(Moves.GROWL, 1); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("BerryPhase"); expect(enemy.status?.effect).toBe(StatusEffect.BURN); diff --git a/src/test/moves/ceaseless_edge.test.ts b/src/test/moves/ceaseless_edge.test.ts index e98fe462c62..88c8c8cf011 100644 --- a/src/test/moves/ceaseless_edge.test.ts +++ b/src/test/moves/ceaseless_edge.test.ts @@ -11,7 +11,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; - describe("Moves - Ceaseless Edge", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -34,8 +33,8 @@ describe("Moves - Ceaseless Edge", () => { game.override.enemyPassiveAbility(Abilities.RUN_AWAY); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.CEASELESS_EDGE, Moves.SPLASH, Moves.ROAR]); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.moveset([ Moves.CEASELESS_EDGE, Moves.SPLASH, Moves.ROAR ]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); vi.spyOn(allMoves[Moves.CEASELESS_EDGE], "accuracy", "get").mockReturnValue(100); }); @@ -43,7 +42,7 @@ describe("Moves - Ceaseless Edge", () => { test( "move should hit and apply spikes", async () => { - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -68,7 +67,7 @@ describe("Moves - Ceaseless Edge", () => { "move should hit twice with multi lens and apply two layers of spikes", async () => { game.override.startingHeldItems([{ name: "MULTI_LENS" }]); - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -95,7 +94,7 @@ describe("Moves - Ceaseless Edge", () => { game.override.startingHeldItems([{ name: "MULTI_LENS" }]); game.override.startingWave(5); - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); game.move.select(Moves.CEASELESS_EDGE); await game.phaseInterceptor.to(MoveEffectPhase, false); diff --git a/src/test/moves/chilly_reception.test.ts b/src/test/moves/chilly_reception.test.ts index 6c8e8172670..664ca242b20 100644 --- a/src/test/moves/chilly_reception.test.ts +++ b/src/test/moves/chilly_reception.test.ts @@ -24,7 +24,7 @@ describe("Moves - Chilly Reception", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("single") - .moveset([Moves.CHILLY_RECEPTION, Moves.SNOWSCAPE]) + .moveset([ Moves.CHILLY_RECEPTION, Moves.SNOWSCAPE ]) .enemyMoveset(Array(4).fill(Moves.SPLASH)) .enemyAbility(Abilities.NONE) .ability(Abilities.NONE); @@ -32,7 +32,7 @@ describe("Moves - Chilly Reception", () => { }); it("should still change the weather if user can't switch out", async () => { - await game.classicMode.startBattle([Species.SLOWKING]); + await game.classicMode.startBattle([ Species.SLOWKING ]); game.move.select(Moves.CHILLY_RECEPTION); @@ -41,7 +41,7 @@ describe("Moves - Chilly Reception", () => { }); it("should switch out even if it's snowing", async () => { - await game.classicMode.startBattle([Species.SLOWKING, Species.MEOWTH]); + await game.classicMode.startBattle([ Species.SLOWKING, Species.MEOWTH ]); // first turn set up snow with snowscape, try chilly reception on second turn game.move.select(Moves.SNOWSCAPE); await game.phaseInterceptor.to("BerryPhase", false); @@ -58,7 +58,7 @@ describe("Moves - Chilly Reception", () => { it("happy case - switch out and weather changes", async () => { - await game.classicMode.startBattle([Species.SLOWKING, Species.MEOWTH]); + await game.classicMode.startBattle([ Species.SLOWKING, Species.MEOWTH ]); game.move.select(Moves.CHILLY_RECEPTION); game.doSelectPartyPokemon(1); @@ -71,11 +71,11 @@ describe("Moves - Chilly Reception", () => { // enemy uses another move and weather doesn't change it("check case - enemy not selecting chilly reception doesn't change weather ", async () => { game.override.battleType("single") - .enemyMoveset([Moves.CHILLY_RECEPTION, Moves.TACKLE]) + .enemyMoveset([ Moves.CHILLY_RECEPTION, Moves.TACKLE ]) .enemyAbility(Abilities.NONE) .moveset(Array(4).fill(Moves.SPLASH)); - await game.classicMode.startBattle([Species.SLOWKING, Species.MEOWTH]); + await game.classicMode.startBattle([ Species.SLOWKING, Species.MEOWTH ]); game.move.select(Moves.SPLASH); await game.forceEnemyMove(Moves.TACKLE); @@ -90,9 +90,9 @@ describe("Moves - Chilly Reception", () => { .enemyMoveset(Array(4).fill(Moves.CHILLY_RECEPTION)) .enemyAbility(Abilities.NONE) .enemySpecies(Species.MAGIKARP) - .moveset([Moves.SPLASH, Moves.THUNDERBOLT]); + .moveset([ Moves.SPLASH, Moves.THUNDERBOLT ]); - await game.classicMode.startBattle([Species.JOLTEON]); + await game.classicMode.startBattle([ Species.JOLTEON ]); const RIVAL_MAGIKARP1 = game.scene.getEnemyPokemon()?.id; game.move.select(Moves.SPLASH); diff --git a/src/test/moves/clangorous_soul.test.ts b/src/test/moves/clangorous_soul.test.ts index 8f0bfb2549f..52e980cc4fa 100644 --- a/src/test/moves/clangorous_soul.test.ts +++ b/src/test/moves/clangorous_soul.test.ts @@ -32,7 +32,7 @@ describe("Moves - Clangorous Soul", () => { game.override.enemySpecies(Species.SNORLAX); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.CLANGOROUS_SOUL]); + game.override.moveset([ Moves.CLANGOROUS_SOUL ]); game.override.enemyMoveset(Moves.SPLASH); }); @@ -40,7 +40,7 @@ describe("Moves - Clangorous Soul", () => { it("raises the user's ATK, DEF, SPATK, SPDEF, and SPD stat stages by 1 each at the cost of 1/3 of its maximum HP", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); @@ -59,7 +59,7 @@ describe("Moves - Clangorous Soul", () => { it("will still take effect if one or more of the involved stat stages are not at max", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); @@ -84,7 +84,7 @@ describe("Moves - Clangorous Soul", () => { it("fails if all stat stages involved are at max", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -108,7 +108,7 @@ describe("Moves - Clangorous Soul", () => { it("fails if the user's health is less than 1/3", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const hpLost = Math.floor(leadPokemon.getMaxHp() / RATIO); diff --git a/src/test/moves/crafty_shield.test.ts b/src/test/moves/crafty_shield.test.ts index 63399c3a86a..93dd4a02538 100644 --- a/src/test/moves/crafty_shield.test.ts +++ b/src/test/moves/crafty_shield.test.ts @@ -10,7 +10,6 @@ import { BerryPhase } from "#app/phases/berry-phase"; import { CommandPhase } from "#app/phases/command-phase"; - describe("Moves - Crafty Shield", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -30,10 +29,10 @@ describe("Moves - Crafty Shield", () => { game.override.battleType("double"); - game.override.moveset([Moves.CRAFTY_SHIELD, Moves.SPLASH, Moves.SWORDS_DANCE]); + game.override.moveset([ Moves.CRAFTY_SHIELD, Moves.SPLASH, Moves.SWORDS_DANCE ]); game.override.enemySpecies(Species.SNORLAX); - game.override.enemyMoveset([Moves.GROWL]); + game.override.enemyMoveset([ Moves.GROWL ]); game.override.enemyAbility(Abilities.INSOMNIA); game.override.startingLevel(100); @@ -43,7 +42,7 @@ describe("Moves - Crafty Shield", () => { test( "should protect the user and allies from status moves", async () => { - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerField(); @@ -62,9 +61,9 @@ describe("Moves - Crafty Shield", () => { test( "should not protect the user and allies from attack moves", async () => { - game.override.enemyMoveset([Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE ]); - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerField(); @@ -84,9 +83,9 @@ describe("Moves - Crafty Shield", () => { "should protect the user and allies from moves that ignore other protection", async () => { game.override.enemySpecies(Species.DUSCLOPS); - game.override.enemyMoveset([Moves.CURSE]); + game.override.enemyMoveset([ Moves.CURSE ]); - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerField(); @@ -105,7 +104,7 @@ describe("Moves - Crafty Shield", () => { test( "should not block allies' self-targeted moves", async () => { - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerField(); diff --git a/src/test/moves/destiny_bond.test.ts b/src/test/moves/destiny_bond.test.ts new file mode 100644 index 00000000000..4b4c8782862 --- /dev/null +++ b/src/test/moves/destiny_bond.test.ts @@ -0,0 +1,255 @@ +import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; +import { allMoves } from "#app/data/move"; +import { Abilities } from "#enums/abilities"; +import { ArenaTagType } from "#enums/arena-tag-type"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { BattlerIndex } from "#app/battle"; +import { StatusEffect } from "#enums/status-effect"; +import { PokemonInstantReviveModifier } from "#app/modifier/modifier"; + + +describe("Moves - Destiny Bond", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + const defaultParty = [ Species.BULBASAUR, Species.SQUIRTLE ]; + const enemyFirst = [ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]; + const playerFirst = [ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override.battleType("single") + .ability(Abilities.UNNERVE) // Pre-emptively prevent flakiness from opponent berries + .enemySpecies(Species.RATTATA) + .enemyAbility(Abilities.RUN_AWAY) + .startingLevel(100) // Make sure tested moves KO + .enemyLevel(5) + .enemyMoveset(Moves.DESTINY_BOND); + }); + + it("should KO the opponent on the same turn", async () => { + const moveToUse = Moves.TACKLE; + + game.override.moveset(moveToUse); + await game.classicMode.startBattle(defaultParty); + + const enemyPokemon = game.scene.getEnemyPokemon(); + const playerPokemon = game.scene.getPlayerPokemon(); + + game.move.select(moveToUse); + await game.setTurnOrder(enemyFirst); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemyPokemon?.isFainted()).toBe(true); + expect(playerPokemon?.isFainted()).toBe(true); + }); + + it("should KO the opponent on the next turn", async () => { + const moveToUse = Moves.TACKLE; + + game.override.moveset([ Moves.SPLASH, moveToUse ]); + await game.classicMode.startBattle(defaultParty); + + const enemyPokemon = game.scene.getEnemyPokemon(); + const playerPokemon = game.scene.getPlayerPokemon(); + + // Turn 1: Enemy uses Destiny Bond and doesn't faint + game.move.select(Moves.SPLASH); + await game.setTurnOrder(playerFirst); + await game.toNextTurn(); + + expect(enemyPokemon?.isFainted()).toBe(false); + expect(playerPokemon?.isFainted()).toBe(false); + + // Turn 2: Player KO's the enemy before the enemy's turn + game.move.select(moveToUse); + await game.setTurnOrder(playerFirst); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemyPokemon?.isFainted()).toBe(true); + expect(playerPokemon?.isFainted()).toBe(true); + }); + + it("should fail if used twice in a row", async () => { + const moveToUse = Moves.TACKLE; + + game.override.moveset([ Moves.SPLASH, moveToUse ]); + await game.classicMode.startBattle(defaultParty); + + const enemyPokemon = game.scene.getEnemyPokemon(); + const playerPokemon = game.scene.getPlayerPokemon(); + + // Turn 1: Enemy uses Destiny Bond and doesn't faint + game.move.select(Moves.SPLASH); + await game.setTurnOrder(enemyFirst); + await game.toNextTurn(); + + expect(enemyPokemon?.isFainted()).toBe(false); + expect(playerPokemon?.isFainted()).toBe(false); + + // Turn 2: Enemy should fail Destiny Bond then get KO'd + game.move.select(moveToUse); + await game.setTurnOrder(enemyFirst); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemyPokemon?.isFainted()).toBe(true); + expect(playerPokemon?.isFainted()).toBe(false); + }); + + it("should not KO the opponent if the user dies to weather", async () => { + // Opponent will be reduced to 1 HP by False Swipe, then faint to Sandstorm + const moveToUse = Moves.FALSE_SWIPE; + + game.override.moveset(moveToUse) + .ability(Abilities.SAND_STREAM); + await game.classicMode.startBattle(defaultParty); + + const enemyPokemon = game.scene.getEnemyPokemon(); + const playerPokemon = game.scene.getPlayerPokemon(); + + game.move.select(moveToUse); + await game.setTurnOrder(enemyFirst); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemyPokemon?.isFainted()).toBe(true); + expect(playerPokemon?.isFainted()).toBe(false); + }); + + it("should not KO the opponent if the user had another turn", async () => { + const moveToUse = Moves.TACKLE; + + game.override.moveset([ Moves.SPORE, moveToUse ]); + await game.classicMode.startBattle(defaultParty); + + const enemyPokemon = game.scene.getEnemyPokemon(); + const playerPokemon = game.scene.getPlayerPokemon(); + + // Turn 1: Enemy uses Destiny Bond and doesn't faint + game.move.select(Moves.SPORE); + await game.setTurnOrder(enemyFirst); + await game.toNextTurn(); + + expect(enemyPokemon?.isFainted()).toBe(false); + expect(playerPokemon?.isFainted()).toBe(false); + expect(enemyPokemon?.status?.effect).toBe(StatusEffect.SLEEP); + + // Turn 2: Enemy should skip a turn due to sleep, then get KO'd + game.move.select(moveToUse); + await game.setTurnOrder(enemyFirst); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemyPokemon?.isFainted()).toBe(true); + expect(playerPokemon?.isFainted()).toBe(false); + }); + + it("should not KO an ally", async () => { + game.override.moveset([ Moves.DESTINY_BOND, Moves.CRUNCH ]) + .battleType("double"); + await game.classicMode.startBattle([ Species.SHEDINJA, Species.BULBASAUR, Species.SQUIRTLE ]); + + const enemyPokemon0 = game.scene.getEnemyField()[0]; + const enemyPokemon1 = game.scene.getEnemyField()[1]; + const playerPokemon0 = game.scene.getPlayerField()[0]; + const playerPokemon1 = game.scene.getPlayerField()[1]; + + // Shedinja uses Destiny Bond, then ally Bulbasaur KO's Shedinja with Crunch + game.move.select(Moves.DESTINY_BOND, 0); + game.move.select(Moves.CRUNCH, 1, BattlerIndex.PLAYER); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemyPokemon0?.isFainted()).toBe(false); + expect(enemyPokemon1?.isFainted()).toBe(false); + expect(playerPokemon0?.isFainted()).toBe(true); + expect(playerPokemon1?.isFainted()).toBe(false); + }); + + it("should not cause a crash if the user is KO'd by Ceaseless Edge", async () => { + const moveToUse = Moves.CEASELESS_EDGE; + vi.spyOn(allMoves[moveToUse], "accuracy", "get").mockReturnValue(100); + + game.override.moveset(moveToUse); + await game.classicMode.startBattle(defaultParty); + + const enemyPokemon = game.scene.getEnemyPokemon(); + const playerPokemon = game.scene.getPlayerPokemon(); + + game.move.select(moveToUse); + await game.setTurnOrder(enemyFirst); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemyPokemon?.isFainted()).toBe(true); + expect(playerPokemon?.isFainted()).toBe(true); + + // Ceaseless Edge spikes effect should still activate + const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag; + expect(tagAfter.tagType).toBe(ArenaTagType.SPIKES); + expect(tagAfter.layers).toBe(1); + }); + + it("should not cause a crash if the user is KO'd by Pledge moves", async () => { + game.override.moveset([ Moves.GRASS_PLEDGE, Moves.WATER_PLEDGE ]) + .battleType("double"); + await game.classicMode.startBattle(defaultParty); + + const enemyPokemon0 = game.scene.getEnemyField()[0]; + const enemyPokemon1 = game.scene.getEnemyField()[1]; + const playerPokemon0 = game.scene.getPlayerField()[0]; + const playerPokemon1 = game.scene.getPlayerField()[1]; + + game.move.select(Moves.GRASS_PLEDGE, 0, BattlerIndex.ENEMY); + game.move.select(Moves.WATER_PLEDGE, 1, BattlerIndex.ENEMY); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2 ]); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemyPokemon0?.isFainted()).toBe(true); + expect(enemyPokemon1?.isFainted()).toBe(false); + expect(playerPokemon0?.isFainted()).toBe(false); + expect(playerPokemon1?.isFainted()).toBe(true); + + // Pledge secondary effect should still activate + const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.GRASS_WATER_PLEDGE, ArenaTagSide.ENEMY) as ArenaTrapTag; + expect(tagAfter.tagType).toBe(ArenaTagType.GRASS_WATER_PLEDGE); + }); + + /** + * In particular, this should prevent something like + * {@link https://github.com/pagefaultgames/pokerogue/issues/4219} + * from occurring with fainting by KO'ing a Destiny Bond user with U-Turn. + */ + it("should not allow the opponent to revive via Reviver Seed", async () => { + const moveToUse = Moves.TACKLE; + + game.override.moveset(moveToUse) + .startingHeldItems([{ name: "REVIVER_SEED" }]); + await game.classicMode.startBattle(defaultParty); + + const enemyPokemon = game.scene.getEnemyPokemon(); + const playerPokemon = game.scene.getPlayerPokemon(); + + game.move.select(moveToUse); + await game.setTurnOrder(enemyFirst); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemyPokemon?.isFainted()).toBe(true); + expect(playerPokemon?.isFainted()).toBe(true); + + // Check that the Tackle user's Reviver Seed did not activate + const revSeeds = game.scene.getModifiers(PokemonInstantReviveModifier).filter(m => m.pokemonId === playerPokemon?.id); + expect(revSeeds.length).toBe(1); + }); +}); diff --git a/src/test/moves/diamond_storm.test.ts b/src/test/moves/diamond_storm.test.ts new file mode 100644 index 00000000000..6e5be2a790d --- /dev/null +++ b/src/test/moves/diamond_storm.test.ts @@ -0,0 +1,46 @@ +import { allMoves } from "#app/data/move"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { Stat } from "#enums/stat"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +describe("Moves - Diamond Storm", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([ Moves.DIAMOND_STORM ]) + .battleType("single") + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should only increase defense once even if hitting 2 pokemon", async () => { + game.override.battleType("double"); + const diamondStorm = allMoves[Moves.DIAMOND_STORM]; + vi.spyOn(diamondStorm, "chance", "get").mockReturnValue(100); + vi.spyOn(diamondStorm, "accuracy", "get").mockReturnValue(100); + await game.classicMode.startBattle([ Species.FEEBAS ]); + + game.move.select(Moves.DIAMOND_STORM); + await game.phaseInterceptor.to("BerryPhase"); + + expect(game.scene.getPlayerPokemon()!.getStatStage(Stat.DEF)).toBe(2); + }); +}); diff --git a/src/test/moves/disable.test.ts b/src/test/moves/disable.test.ts index a35d294e91f..3748598fa90 100644 --- a/src/test/moves/disable.test.ts +++ b/src/test/moves/disable.test.ts @@ -26,7 +26,7 @@ describe("Moves - Disable", () => { .battleType("single") .ability(Abilities.BALL_FETCH) .enemyAbility(Abilities.BALL_FETCH) - .moveset([Moves.DISABLE, Moves.SPLASH]) + .moveset([ Moves.DISABLE, Moves.SPLASH ]) .enemyMoveset(Moves.SPLASH) .starterSpecies(Species.PIKACHU) .enemySpecies(Species.SHUCKLE); @@ -38,7 +38,7 @@ describe("Moves - Disable", () => { const enemyMon = game.scene.getEnemyPokemon()!; game.move.select(Moves.DISABLE); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); expect(enemyMon.getMoveHistory()).toHaveLength(1); @@ -52,7 +52,7 @@ describe("Moves - Disable", () => { const enemyMon = game.scene.getEnemyPokemon()!; game.move.select(Moves.DISABLE); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.toNextTurn(); expect(playerMon.getMoveHistory()[0]).toMatchObject({ move: Moves.DISABLE, result: MoveResult.FAIL }); @@ -65,7 +65,7 @@ describe("Moves - Disable", () => { const enemyMon = game.scene.getEnemyPokemon()!; game.move.select(Moves.DISABLE); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); game.move.select(Moves.SPLASH); @@ -78,14 +78,14 @@ describe("Moves - Disable", () => { }, 20000); it("cannot disable STRUGGLE", async() => { - game.override.enemyMoveset([Moves.STRUGGLE]); + game.override.enemyMoveset([ Moves.STRUGGLE ]); await game.classicMode.startBattle(); const playerMon = game.scene.getPlayerPokemon()!; const enemyMon = game.scene.getEnemyPokemon()!; game.move.select(Moves.DISABLE); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); expect(playerMon.getLastXMoves()[0].result).toBe(MoveResult.FAIL); @@ -103,7 +103,7 @@ describe("Moves - Disable", () => { // Both mons just used Splash last turn; now have player use Disable. game.move.select(Moves.DISABLE); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.toNextTurn(); const enemyHistory = enemyMon.getMoveHistory(); @@ -113,13 +113,13 @@ describe("Moves - Disable", () => { }, 20000); it("disables NATURE POWER, not the move invoked by it", async() => { - game.override.enemyMoveset([Moves.NATURE_POWER]); + game.override.enemyMoveset([ Moves.NATURE_POWER ]); await game.classicMode.startBattle(); const enemyMon = game.scene.getEnemyPokemon()!; game.move.select(Moves.DISABLE); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); expect(enemyMon.isMoveRestricted(Moves.NATURE_POWER)).toBe(true); diff --git a/src/test/moves/double_team.test.ts b/src/test/moves/double_team.test.ts index fa224c8df9e..62848553e06 100644 --- a/src/test/moves/double_team.test.ts +++ b/src/test/moves/double_team.test.ts @@ -24,16 +24,16 @@ describe("Moves - Double Team", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("single"); - game.override.moveset([Moves.DOUBLE_TEAM]); + game.override.moveset([ Moves.DOUBLE_TEAM ]); game.override.disableCrits(); game.override.ability(Abilities.BALL_FETCH); game.override.enemySpecies(Species.SHUCKLE); game.override.enemyAbility(Abilities.BALL_FETCH); - game.override.enemyMoveset([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE ]); }); it("raises the user's EVA stat stage by 1", async () => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const ally = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/dragon_cheer.test.ts b/src/test/moves/dragon_cheer.test.ts index beaf6ddb520..37b74d44360 100644 --- a/src/test/moves/dragon_cheer.test.ts +++ b/src/test/moves/dragon_cheer.test.ts @@ -27,11 +27,11 @@ describe("Moves - Dragon Cheer", () => { .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH) .enemyLevel(20) - .moveset([Moves.DRAGON_CHEER, Moves.TACKLE, Moves.SPLASH]); + .moveset([ Moves.DRAGON_CHEER, Moves.TACKLE, Moves.SPLASH ]); }); it("increases the user's allies' critical hit ratio by one stage", async () => { - await game.classicMode.startBattle([Species.DRAGONAIR, Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.DRAGONAIR, Species.MAGIKARP ]); const enemy = game.scene.getEnemyField()[0]; @@ -40,7 +40,7 @@ describe("Moves - Dragon Cheer", () => { game.move.select(Moves.DRAGON_CHEER, 0); game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); // After Tackle await game.phaseInterceptor.to("TurnEndPhase"); @@ -48,7 +48,7 @@ describe("Moves - Dragon Cheer", () => { }); it("increases the user's Dragon-type allies' critical hit ratio by two stages", async () => { - await game.classicMode.startBattle([Species.MAGIKARP, Species.DRAGONAIR]); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.DRAGONAIR ]); const enemy = game.scene.getEnemyField()[0]; @@ -57,7 +57,7 @@ describe("Moves - Dragon Cheer", () => { game.move.select(Moves.DRAGON_CHEER, 0); game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); // After Tackle await game.phaseInterceptor.to("TurnEndPhase"); @@ -65,7 +65,7 @@ describe("Moves - Dragon Cheer", () => { }); it("applies the effect based on the allies' type upon use of the move, and do not change if the allies' type changes later in battle", async () => { - await game.classicMode.startBattle([Species.DRAGONAIR, Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.DRAGONAIR, Species.MAGIKARP ]); const magikarp = game.scene.getPlayerField()[1]; const enemy = game.scene.getEnemyField()[0]; @@ -75,7 +75,7 @@ describe("Moves - Dragon Cheer", () => { game.move.select(Moves.DRAGON_CHEER, 0); game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); // After Tackle await game.phaseInterceptor.to("TurnEndPhase"); @@ -84,13 +84,13 @@ describe("Moves - Dragon Cheer", () => { await game.toNextTurn(); // Change Magikarp's type to Dragon - vi.spyOn(magikarp, "getTypes").mockReturnValue([Type.DRAGON]); - expect(magikarp.getTypes()).toEqual([Type.DRAGON]); + vi.spyOn(magikarp, "getTypes").mockReturnValue([ Type.DRAGON ]); + expect(magikarp.getTypes()).toEqual([ Type.DRAGON ]); game.move.select(Moves.SPLASH, 0); game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY); - await game.setTurnOrder([BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.getCritStage).toHaveReturnedWith(1); // getCritStage is called on defender diff --git a/src/test/moves/dragon_rage.test.ts b/src/test/moves/dragon_rage.test.ts index cab8c3f808b..dcbed7107e6 100644 --- a/src/test/moves/dragon_rage.test.ts +++ b/src/test/moves/dragon_rage.test.ts @@ -35,7 +35,7 @@ describe("Moves - Dragon Rage", () => { game.override.battleType("single"); game.override.starterSpecies(Species.SNORLAX); - game.override.moveset([Moves.DRAGON_RAGE]); + game.override.moveset([ Moves.DRAGON_RAGE ]); game.override.ability(Abilities.BALL_FETCH); game.override.passiveAbility(Abilities.BALL_FETCH); game.override.startingLevel(100); @@ -58,7 +58,7 @@ describe("Moves - Dragon Rage", () => { it("ignores weaknesses", async () => { game.override.disableCrits(); - vi.spyOn(enemyPokemon, "getTypes").mockReturnValue([Type.DRAGON]); + vi.spyOn(enemyPokemon, "getTypes").mockReturnValue([ Type.DRAGON ]); game.move.select(Moves.DRAGON_RAGE); await game.phaseInterceptor.to(TurnEndPhase); @@ -68,7 +68,7 @@ describe("Moves - Dragon Rage", () => { it("ignores resistances", async () => { game.override.disableCrits(); - vi.spyOn(enemyPokemon, "getTypes").mockReturnValue([Type.STEEL]); + vi.spyOn(enemyPokemon, "getTypes").mockReturnValue([ Type.STEEL ]); game.move.select(Moves.DRAGON_RAGE); await game.phaseInterceptor.to(TurnEndPhase); @@ -88,7 +88,7 @@ describe("Moves - Dragon Rage", () => { it("ignores stab", async () => { game.override.disableCrits(); - vi.spyOn(partyPokemon, "getTypes").mockReturnValue([Type.DRAGON]); + vi.spyOn(partyPokemon, "getTypes").mockReturnValue([ Type.DRAGON ]); game.move.select(Moves.DRAGON_RAGE); await game.phaseInterceptor.to(TurnEndPhase); diff --git a/src/test/moves/dragon_tail.test.ts b/src/test/moves/dragon_tail.test.ts index dd7193dc97f..cf801eb42c1 100644 --- a/src/test/moves/dragon_tail.test.ts +++ b/src/test/moves/dragon_tail.test.ts @@ -24,7 +24,7 @@ describe("Moves - Dragon Tail", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("single") - .moveset([Moves.DRAGON_TAIL, Moves.SPLASH, Moves.FLAMETHROWER]) + .moveset([ Moves.DRAGON_TAIL, Moves.SPLASH, Moves.FLAMETHROWER ]) .enemySpecies(Species.WAILORD) .enemyMoveset(Moves.SPLASH) .startingLevel(5) @@ -34,7 +34,7 @@ describe("Moves - Dragon Tail", () => { }); it("should cause opponent to flee, and not crash", async () => { - await game.classicMode.startBattle([Species.DRATINI]); + await game.classicMode.startBattle([ Species.DRATINI ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -52,7 +52,7 @@ describe("Moves - Dragon Tail", () => { it("should cause opponent to flee, display ability, and not crash", async () => { game.override.enemyAbility(Abilities.ROUGH_SKIN); - await game.classicMode.startBattle([Species.DRATINI]); + await game.classicMode.startBattle([ Species.DRATINI ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -71,7 +71,7 @@ describe("Moves - Dragon Tail", () => { game.override .battleType("double").enemyMoveset(Moves.SPLASH) .enemyAbility(Abilities.ROUGH_SKIN); - await game.classicMode.startBattle([Species.DRATINI, Species.DRATINI, Species.WAILORD, Species.WAILORD]); + await game.classicMode.startBattle([ Species.DRATINI, Species.DRATINI, Species.WAILORD, Species.WAILORD ]); const leadPokemon = game.scene.getParty()[0]!; @@ -103,7 +103,7 @@ describe("Moves - Dragon Tail", () => { .battleType("double") .enemyMoveset(Moves.SPLASH) .enemyAbility(Abilities.ROUGH_SKIN); - await game.classicMode.startBattle([Species.DRATINI, Species.DRATINI, Species.WAILORD, Species.WAILORD]); + await game.classicMode.startBattle([ Species.DRATINI, Species.DRATINI, Species.WAILORD, Species.WAILORD ]); const leadPokemon = game.scene.getParty()[0]!; const secPokemon = game.scene.getParty()[1]!; @@ -130,7 +130,7 @@ describe("Moves - Dragon Tail", () => { it("doesn't switch out if the target has suction cups", async () => { game.override.enemyAbility(Abilities.SUCTION_CUPS); - await game.classicMode.startBattle([Species.REGIELEKI]); + await game.classicMode.startBattle([ Species.REGIELEKI ]); const enemy = game.scene.getEnemyPokemon()!; @@ -139,4 +139,58 @@ describe("Moves - Dragon Tail", () => { expect(enemy.isFullHp()).toBe(false); }); + + it("should force a switch upon fainting an opponent normally", async () => { + game.override.startingWave(5) + .startingLevel(1000); // To make sure Dragon Tail KO's the opponent + await game.classicMode.startBattle([ Species.DRATINI ]); + + game.move.select(Moves.DRAGON_TAIL); + + await game.toNextTurn(); + + // Make sure the enemy switched to a healthy Pokemon + const enemy = game.scene.getEnemyPokemon()!; + expect(enemy).toBeDefined(); + expect(enemy.isFullHp()).toBe(true); + + // Make sure the enemy has a fainted Pokemon in their party and not on the field + const faintedEnemy = game.scene.getEnemyParty().find(p => !p.isAllowedInBattle()); + expect(faintedEnemy).toBeDefined(); + expect(game.scene.getEnemyField().length).toBe(1); + }); + + it("should not cause a softlock when activating an opponent trainer's reviver seed", async () => { + game.override.startingWave(5) + .enemyHeldItems([{ name: "REVIVER_SEED" }]) + .startingLevel(1000); // To make sure Dragon Tail KO's the opponent + await game.classicMode.startBattle([ Species.DRATINI ]); + + game.move.select(Moves.DRAGON_TAIL); + + await game.toNextTurn(); + + // Make sure the enemy field is not empty and has a revived Pokemon + const enemy = game.scene.getEnemyPokemon()!; + expect(enemy).toBeDefined(); + expect(enemy.hp).toBe(Math.floor(enemy.getMaxHp() / 2)); + expect(game.scene.getEnemyField().length).toBe(1); + }); + + it("should not cause a softlock when activating a player's reviver seed", async () => { + game.override.startingHeldItems([{ name: "REVIVER_SEED" }]) + .enemyMoveset(Moves.DRAGON_TAIL) + .enemyLevel(1000); // To make sure Dragon Tail KO's the player + await game.classicMode.startBattle([ Species.DRATINI, Species.BULBASAUR ]); + + game.move.select(Moves.SPLASH); + + await game.toNextTurn(); + + // Make sure the player's field is not empty and has a revived Pokemon + const dratini = game.scene.getPlayerPokemon()!; + expect(dratini).toBeDefined(); + expect(dratini.hp).toBe(Math.floor(dratini.getMaxHp() / 2)); + expect(game.scene.getPlayerField().length).toBe(1); + }); }); diff --git a/src/test/moves/dynamax_cannon.test.ts b/src/test/moves/dynamax_cannon.test.ts index 6ac0befdb36..9dd48d3c94c 100644 --- a/src/test/moves/dynamax_cannon.test.ts +++ b/src/test/moves/dynamax_cannon.test.ts @@ -27,7 +27,7 @@ describe("Moves - Dynamax Cannon", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([dynamaxCannon.id]); + game.override.moveset([ dynamaxCannon.id ]); game.override.startingLevel(200); // Note that, for Waves 1-10, the level cap is 10 @@ -36,7 +36,7 @@ describe("Moves - Dynamax Cannon", () => { game.override.disableCrits(); game.override.enemySpecies(Species.MAGIKARP); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); vi.spyOn(dynamaxCannon, "calculateBattlePower"); }); @@ -161,7 +161,7 @@ describe("Moves - Dynamax Cannon", () => { ]); game.move.select(dynamaxCannon.id); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(dynamaxCannon.id); diff --git a/src/test/moves/electrify.test.ts b/src/test/moves/electrify.test.ts new file mode 100644 index 00000000000..5d15a825688 --- /dev/null +++ b/src/test/moves/electrify.test.ts @@ -0,0 +1,69 @@ +import { BattlerIndex } from "#app/battle"; +import { Type } from "#app/data/type"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; + +describe("Moves - Electrify", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset(Moves.ELECTRIFY) + .battleType("single") + .startingLevel(100) + .enemySpecies(Species.SNORLAX) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.TACKLE) + .enemyLevel(100); + }); + + it("should convert attacks to Electric type", async () => { + await game.classicMode.startBattle([ Species.EXCADRILL ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyPokemon = game.scene.getEnemyPokemon()!; + vi.spyOn(enemyPokemon, "getMoveType"); + + game.move.select(Moves.ELECTRIFY); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + + await game.phaseInterceptor.to("BerryPhase", false); + expect(enemyPokemon.getMoveType).toHaveLastReturnedWith(Type.ELECTRIC); + expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp()); + }); + + it("should override type changes from abilities", async () => { + game.override.enemyAbility(Abilities.PIXILATE); + + await game.classicMode.startBattle([ Species.EXCADRILL ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyPokemon = game.scene.getPlayerPokemon()!; + vi.spyOn(enemyPokemon, "getMoveType"); + + game.move.select(Moves.ELECTRIFY); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + + await game.phaseInterceptor.to("BerryPhase", false); + expect(enemyPokemon.getMoveType).toHaveLastReturnedWith(Type.ELECTRIC); + expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp()); + }); +}); diff --git a/src/test/moves/fake_out.test.ts b/src/test/moves/fake_out.test.ts index e306ab12a3f..f20b6db3a13 100644 --- a/src/test/moves/fake_out.test.ts +++ b/src/test/moves/fake_out.test.ts @@ -23,7 +23,7 @@ describe("Moves - Fake Out", () => { game.override .battleType("single") .enemySpecies(Species.CORVIKNIGHT) - .moveset([Moves.FAKE_OUT, Moves.SPLASH]) + .moveset([ Moves.FAKE_OUT, Moves.SPLASH ]) .enemyMoveset(Moves.SPLASH) .enemyLevel(10) .startingLevel(10) // prevent LevelUpPhase from happening @@ -31,7 +31,7 @@ describe("Moves - Fake Out", () => { }); it("can only be used on the first turn a pokemon is sent out in a battle", async() => { - await game.classicMode.startBattle([Species.FEEBAS]); + await game.classicMode.startBattle([ Species.FEEBAS ]); const enemy = game.scene.getEnemyPokemon()!; @@ -49,7 +49,7 @@ describe("Moves - Fake Out", () => { // This is a PokeRogue buff to Fake Out it("can be used at the start of every wave even if the pokemon wasn't recalled", async() => { - await game.classicMode.startBattle([Species.FEEBAS]); + await game.classicMode.startBattle([ Species.FEEBAS ]); const enemy = game.scene.getEnemyPokemon()!; enemy.damageAndUpdate(enemy.getMaxHp() - 1); @@ -65,7 +65,7 @@ describe("Moves - Fake Out", () => { it("can be used again if recalled and sent back out", async() => { game.override.startingWave(4); - await game.classicMode.startBattle([Species.FEEBAS, Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.FEEBAS, Species.MAGIKARP ]); const enemy1 = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/fillet_away.test.ts b/src/test/moves/fillet_away.test.ts index d8dd74a259c..aa3243270cb 100644 --- a/src/test/moves/fillet_away.test.ts +++ b/src/test/moves/fillet_away.test.ts @@ -33,7 +33,7 @@ describe("Moves - FILLET AWAY", () => { game.override.enemySpecies(Species.SNORLAX); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.FILLET_AWAY]); + game.override.moveset([ Moves.FILLET_AWAY ]); game.override.enemyMoveset(Moves.SPLASH); }); @@ -41,7 +41,7 @@ describe("Moves - FILLET AWAY", () => { test("raises the user's ATK, SPATK, and SPD stat stages by 2 each, at the cost of 1/2 of its maximum HP", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); @@ -58,7 +58,7 @@ describe("Moves - FILLET AWAY", () => { test("still takes effect if one or more of the involved stat stages are not at max", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); @@ -79,7 +79,7 @@ describe("Moves - FILLET AWAY", () => { test("fails if all stat stages involved are at max", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -99,7 +99,7 @@ describe("Moves - FILLET AWAY", () => { test("fails if the user's health is less than 1/2", async() => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const hpLost = toDmgValue(leadPokemon.getMaxHp() / RATIO); diff --git a/src/test/moves/fissure.test.ts b/src/test/moves/fissure.test.ts index 8689ce4079e..16c3faa6827 100644 --- a/src/test/moves/fissure.test.ts +++ b/src/test/moves/fissure.test.ts @@ -32,7 +32,7 @@ describe("Moves - Fissure", () => { game.override.disableCrits(); game.override.starterSpecies(Species.SNORLAX); - game.override.moveset([Moves.FISSURE]); + game.override.moveset([ Moves.FISSURE ]); game.override.passiveAbility(Abilities.BALL_FETCH); game.override.startingLevel(100); diff --git a/src/test/moves/flame_burst.test.ts b/src/test/moves/flame_burst.test.ts index b2858af2b24..feedee3b7bc 100644 --- a/src/test/moves/flame_burst.test.ts +++ b/src/test/moves/flame_burst.test.ts @@ -36,18 +36,18 @@ describe("Moves - Flame Burst", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("double"); - game.override.moveset([Moves.FLAME_BURST, Moves.SPLASH]); + game.override.moveset([ Moves.FLAME_BURST, Moves.SPLASH ]); game.override.disableCrits(); game.override.ability(Abilities.UNNERVE); game.override.startingWave(4); game.override.enemySpecies(Species.SHUCKLE); game.override.enemyAbility(Abilities.BALL_FETCH); - game.override.enemyMoveset([Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH ]); }); it("inflicts damage to the target's ally equal to 1/16 of its max HP", async () => { - await game.startBattle([Species.PIKACHU, Species.PIKACHU]); - const [leftEnemy, rightEnemy] = game.scene.getEnemyField(); + await game.startBattle([ Species.PIKACHU, Species.PIKACHU ]); + const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField(); game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex()); game.move.select(Moves.SPLASH, 1); @@ -60,8 +60,8 @@ describe("Moves - Flame Burst", () => { it("does not inflict damage to the target's ally if the target was not affected by Flame Burst", async () => { game.override.enemyAbility(Abilities.FLASH_FIRE); - await game.startBattle([Species.PIKACHU, Species.PIKACHU]); - const [leftEnemy, rightEnemy] = game.scene.getEnemyField(); + await game.startBattle([ Species.PIKACHU, Species.PIKACHU ]); + const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField(); game.move.select(Moves.FLAME_BURST, 0, leftEnemy.getBattlerIndex()); game.move.select(Moves.SPLASH, 1); @@ -72,8 +72,8 @@ describe("Moves - Flame Burst", () => { }); it("does not interact with the target ally's abilities", async () => { - await game.startBattle([Species.PIKACHU, Species.PIKACHU]); - const [leftEnemy, rightEnemy] = game.scene.getEnemyField(); + await game.startBattle([ Species.PIKACHU, Species.PIKACHU ]); + const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField(); vi.spyOn(rightEnemy, "getAbility").mockReturnValue(allAbilities[Abilities.FLASH_FIRE]); @@ -86,8 +86,8 @@ describe("Moves - Flame Burst", () => { }); it("effect damage is prevented by Magic Guard", async () => { - await game.startBattle([Species.PIKACHU, Species.PIKACHU]); - const [leftEnemy, rightEnemy] = game.scene.getEnemyField(); + await game.startBattle([ Species.PIKACHU, Species.PIKACHU ]); + const [ leftEnemy, rightEnemy ] = game.scene.getEnemyField(); vi.spyOn(rightEnemy, "getAbility").mockReturnValue(allAbilities[Abilities.MAGIC_GUARD]); diff --git a/src/test/moves/flower_shield.test.ts b/src/test/moves/flower_shield.test.ts index f5fe8d532cc..1a5cd326fd8 100644 --- a/src/test/moves/flower_shield.test.ts +++ b/src/test/moves/flower_shield.test.ts @@ -29,14 +29,14 @@ describe("Moves - Flower Shield", () => { game.override.ability(Abilities.NONE); game.override.enemyAbility(Abilities.NONE); game.override.battleType("single"); - game.override.moveset([Moves.FLOWER_SHIELD, Moves.SPLASH]); + game.override.moveset([ Moves.FLOWER_SHIELD, Moves.SPLASH ]); game.override.enemyMoveset(Moves.SPLASH); }); it("raises DEF stat stage by 1 for all Grass-type Pokemon on the field by one stage - single battle", async () => { game.override.enemySpecies(Species.CHERRIM); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const cherrim = game.scene.getEnemyPokemon()!; const magikarp = game.scene.getPlayerPokemon()!; @@ -53,7 +53,7 @@ describe("Moves - Flower Shield", () => { it("raises DEF stat stage by 1 for all Grass-type Pokemon on the field by one stage - double battle", async () => { game.override.enemySpecies(Species.MAGIKARP).startingBiome(Biome.GRASS).battleType("double"); - await game.startBattle([Species.CHERRIM, Species.MAGIKARP]); + await game.startBattle([ Species.CHERRIM, Species.MAGIKARP ]); const field = game.scene.getField(true); const grassPokemons = field.filter(p => p.getTypes().includes(Type.GRASS)); @@ -75,10 +75,10 @@ describe("Moves - Flower Shield", () => { */ it("does not raise DEF stat stage for a Pokemon in semi-vulnerable state", async () => { game.override.enemySpecies(Species.PARAS); - game.override.enemyMoveset([Moves.DIG, Moves.DIG, Moves.DIG, Moves.DIG]); + game.override.enemyMoveset([ Moves.DIG, Moves.DIG, Moves.DIG, Moves.DIG ]); game.override.enemyLevel(50); - await game.startBattle([Species.CHERRIM]); + await game.startBattle([ Species.CHERRIM ]); const paras = game.scene.getEnemyPokemon()!; const cherrim = game.scene.getPlayerPokemon()!; @@ -97,7 +97,7 @@ describe("Moves - Flower Shield", () => { it("does nothing if there are no Grass-type Pokemon on the field", async () => { game.override.enemySpecies(Species.MAGIKARP); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const enemy = game.scene.getEnemyPokemon()!; const ally = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/focus_punch.test.ts b/src/test/moves/focus_punch.test.ts index b839c228b68..386eb2537ee 100644 --- a/src/test/moves/focus_punch.test.ts +++ b/src/test/moves/focus_punch.test.ts @@ -11,7 +11,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Moves - Focus Punch", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -31,7 +30,7 @@ describe("Moves - Focus Punch", () => { game.override .battleType("single") .ability(Abilities.UNNERVE) - .moveset([Moves.FOCUS_PUNCH]) + .moveset([ Moves.FOCUS_PUNCH ]) .enemySpecies(Species.GROUDON) .enemyAbility(Abilities.INSOMNIA) .enemyMoveset(Moves.SPLASH) @@ -42,7 +41,7 @@ describe("Moves - Focus Punch", () => { it( "should deal damage at the end of turn if uninterrupted", async () => { - await game.startBattle([Species.CHARIZARD]); + await game.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -67,9 +66,9 @@ describe("Moves - Focus Punch", () => { it( "should fail if the user is hit", async () => { - game.override.enemyMoveset([Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE ]); - await game.startBattle([Species.CHARIZARD]); + await game.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -94,9 +93,9 @@ describe("Moves - Focus Punch", () => { it( "should be cancelled if the user falls asleep mid-turn", async () => { - game.override.enemyMoveset([Moves.SPORE]); + game.override.enemyMoveset([ Moves.SPORE ]); - await game.startBattle([Species.CHARIZARD]); + await game.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -120,7 +119,7 @@ describe("Moves - Focus Punch", () => { /** Guarantee a Trainer battle with multiple enemy Pokemon */ game.override.startingWave(25); - await game.startBattle([Species.CHARIZARD]); + await game.startBattle([ Species.CHARIZARD ]); game.forceEnemyToSwitch(); game.move.select(Moves.FOCUS_PUNCH); diff --git a/src/test/moves/follow_me.test.ts b/src/test/moves/follow_me.test.ts index 28fb1045a8c..fba7937f812 100644 --- a/src/test/moves/follow_me.test.ts +++ b/src/test/moves/follow_me.test.ts @@ -9,7 +9,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - describe("Moves - Follow Me", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -32,14 +31,14 @@ describe("Moves - Follow Me", () => { game.override.enemySpecies(Species.SNORLAX); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK]); - game.override.enemyMoveset([Moves.TACKLE, Moves.FOLLOW_ME, Moves.SPLASH]); + game.override.moveset([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + game.override.enemyMoveset([ Moves.TACKLE, Moves.FOLLOW_ME, Moves.SPLASH ]); }); test( "move should redirect enemy attacks to the user", async () => { - await game.classicMode.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerField(); @@ -60,7 +59,7 @@ describe("Moves - Follow Me", () => { test( "move should redirect enemy attacks to the first ally that uses it", async () => { - await game.classicMode.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerField(); @@ -84,9 +83,9 @@ describe("Moves - Follow Me", () => { "move effect should be bypassed by Stalwart", async () => { game.override.ability(Abilities.STALWART); - game.override.moveset([Moves.QUICK_ATTACK]); + game.override.moveset([ Moves.QUICK_ATTACK ]); - await game.classicMode.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); const enemyPokemon = game.scene.getEnemyField(); @@ -108,9 +107,9 @@ describe("Moves - Follow Me", () => { test( "move effect should be bypassed by Snipe Shot", async () => { - game.override.moveset([Moves.SNIPE_SHOT]); + game.override.moveset([ Moves.SNIPE_SHOT ]); - await game.classicMode.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); const enemyPokemon = game.scene.getEnemyField(); diff --git a/src/test/moves/foresight.test.ts b/src/test/moves/foresight.test.ts index d58097691fd..1195cd0b71b 100644 --- a/src/test/moves/foresight.test.ts +++ b/src/test/moves/foresight.test.ts @@ -27,7 +27,7 @@ describe("Moves - Foresight", () => { .enemyMoveset(Moves.SPLASH) .enemyLevel(5) .starterSpecies(Species.MAGIKARP) - .moveset([Moves.FORESIGHT, Moves.QUICK_ATTACK, Moves.MACH_PUNCH]); + .moveset([ Moves.FORESIGHT, Moves.QUICK_ATTACK, Moves.MACH_PUNCH ]); }); it("should allow Normal and Fighting moves to hit Ghost types", async () => { @@ -54,7 +54,7 @@ describe("Moves - Foresight", () => { }); it("should ignore target's evasiveness boosts", async () => { - game.override.enemyMoveset([Moves.MINIMIZE]); + game.override.enemyMoveset([ Moves.MINIMIZE ]); await game.startBattle(); const pokemon = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/freeze_dry.test.ts b/src/test/moves/freeze_dry.test.ts index b901f04e6a1..c09d12fa597 100644 --- a/src/test/moves/freeze_dry.test.ts +++ b/src/test/moves/freeze_dry.test.ts @@ -28,7 +28,7 @@ describe("Moves - Freeze-Dry", () => { .enemyMoveset(Moves.SPLASH) .starterSpecies(Species.FEEBAS) .ability(Abilities.BALL_FETCH) - .moveset([Moves.FREEZE_DRY]); + .moveset([ Moves.FREEZE_DRY ]); }); it("should deal 2x damage to pure water types", async () => { @@ -38,7 +38,7 @@ describe("Moves - Freeze-Dry", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.FREEZE_DRY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(2); @@ -52,7 +52,7 @@ describe("Moves - Freeze-Dry", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.FREEZE_DRY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(4); @@ -66,7 +66,7 @@ describe("Moves - Freeze-Dry", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.FREEZE_DRY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(1); @@ -81,7 +81,7 @@ describe("Moves - Freeze-Dry", () => { vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.FREEZE_DRY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(2); @@ -89,14 +89,14 @@ describe("Moves - Freeze-Dry", () => { // enable once Electrify is implemented (and the interaction is fixed, as above) it.todo("should deal 2x damage to water types under Electrify", async () => { - game.override.enemyMoveset([Moves.ELECTRIFY]); + game.override.enemyMoveset([ Moves.ELECTRIFY ]); await game.classicMode.startBattle(); const enemy = game.scene.getEnemyPokemon()!; vi.spyOn(enemy, "getMoveEffectiveness"); game.move.select(Moves.FREEZE_DRY); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(2); diff --git a/src/test/moves/freezy_frost.test.ts b/src/test/moves/freezy_frost.test.ts index ad5163dae48..09d7779474f 100644 --- a/src/test/moves/freezy_frost.test.ts +++ b/src/test/moves/freezy_frost.test.ts @@ -33,7 +33,7 @@ describe("Moves - Freezy Frost", () => { .moveset([ Moves.FREEZY_FROST, Moves.HOWL, Moves.SPLASH ]) .ability(Abilities.BALL_FETCH); - vi.spyOn(allMoves[ Moves.FREEZY_FROST ], "accuracy", "get").mockReturnValue(100); + vi.spyOn(allMoves[Moves.FREEZY_FROST], "accuracy", "get").mockReturnValue(100); }); it( diff --git a/src/test/moves/fusion_bolt.test.ts b/src/test/moves/fusion_bolt.test.ts index db31863ad03..4e35b939abf 100644 --- a/src/test/moves/fusion_bolt.test.ts +++ b/src/test/moves/fusion_bolt.test.ts @@ -23,12 +23,12 @@ describe("Moves - Fusion Bolt", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([fusionBolt]); + game.override.moveset([ fusionBolt ]); game.override.startingLevel(1); game.override.enemySpecies(Species.RESHIRAM); game.override.enemyAbility(Abilities.ROUGH_SKIN); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); game.override.battleType("single"); game.override.startingWave(97); diff --git a/src/test/moves/fusion_flare.test.ts b/src/test/moves/fusion_flare.test.ts index 0a8f6f9115d..162cefcfb1e 100644 --- a/src/test/moves/fusion_flare.test.ts +++ b/src/test/moves/fusion_flare.test.ts @@ -24,11 +24,11 @@ describe("Moves - Fusion Flare", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([fusionFlare]); + game.override.moveset([ fusionFlare ]); game.override.startingLevel(1); game.override.enemySpecies(Species.RATTATA); - game.override.enemyMoveset([Moves.REST, Moves.REST, Moves.REST, Moves.REST]); + game.override.enemyMoveset([ Moves.REST, Moves.REST, Moves.REST, Moves.REST ]); game.override.battleType("single"); game.override.startingWave(97); diff --git a/src/test/moves/fusion_flare_bolt.test.ts b/src/test/moves/fusion_flare_bolt.test.ts index a8372fcaaab..0d9b9898276 100644 --- a/src/test/moves/fusion_flare_bolt.test.ts +++ b/src/test/moves/fusion_flare_bolt.test.ts @@ -30,11 +30,11 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([fusionFlare.id, fusionBolt.id]); + game.override.moveset([ fusionFlare.id, fusionBolt.id ]); game.override.startingLevel(1); game.override.enemySpecies(Species.RESHIRAM); - game.override.enemyMoveset([Moves.REST, Moves.REST, Moves.REST, Moves.REST]); + game.override.enemyMoveset([ Moves.REST, Moves.REST, Moves.REST, Moves.REST ]); game.override.battleType("double"); game.override.startingWave(97); @@ -54,7 +54,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { game.move.select(fusionBolt.id, 1, BattlerIndex.ENEMY); // Force user party to act before enemy party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id); @@ -77,7 +77,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { game.move.select(fusionFlare.id, 1, BattlerIndex.ENEMY); // Force user party to act before enemy party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id); @@ -100,7 +100,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { game.move.select(fusionBolt.id, 1, BattlerIndex.PLAYER); // Force first enemy to act (and fail) in between party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id); @@ -119,7 +119,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { }, 20000); it("FUSION_FLARE should not double power of subsequent FUSION_BOLT if a move succeeded in between", async () => { - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); await game.startBattle([ Species.ZEKROM, Species.ZEKROM @@ -129,7 +129,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { game.move.select(fusionBolt.id, 1, BattlerIndex.ENEMY); // Force first enemy to act in between party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionFlare.id); @@ -156,7 +156,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { game.move.select(fusionFlare.id, 1, BattlerIndex.PLAYER); // Force user party to act before enemy party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id); @@ -170,7 +170,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { }, 20000); it("FUSION_FLARE and FUSION_BOLT alternating throughout turn should double power of subsequent moves", async () => { - game.override.enemyMoveset([fusionFlare.id, fusionFlare.id, fusionFlare.id, fusionFlare.id]); + game.override.enemyMoveset([ fusionFlare.id, fusionFlare.id, fusionFlare.id, fusionFlare.id ]); await game.startBattle([ Species.ZEKROM, Species.ZEKROM @@ -186,12 +186,12 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { // Mock stats by replacing entries in copy with desired values for specific stats const stats = { enemy: [ - [...enemyParty[0].stats], - [...enemyParty[1].stats], + [ ...enemyParty[0].stats ], + [ ...enemyParty[1].stats ], ], player: [ - [...party[0].stats], - [...party[1].stats], + [ ...party[0].stats ], + [ ...party[1].stats ], ] }; @@ -205,7 +205,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { game.move.select(fusionBolt.id, 1, BattlerIndex.ENEMY); // Force first enemy to act in between party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id); @@ -229,7 +229,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { }, 20000); it("FUSION_FLARE and FUSION_BOLT alternating throughout turn should double power of subsequent moves if moves are aimed at allies", async () => { - game.override.enemyMoveset([fusionFlare.id, fusionFlare.id, fusionFlare.id, fusionFlare.id]); + game.override.enemyMoveset([ fusionFlare.id, fusionFlare.id, fusionFlare.id, fusionFlare.id ]); await game.startBattle([ Species.ZEKROM, Species.ZEKROM @@ -245,12 +245,12 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { // Mock stats by replacing entries in copy with desired values for specific stats const stats = { enemy: [ - [...enemyParty[0].stats], - [...enemyParty[1].stats], + [ ...enemyParty[0].stats ], + [ ...enemyParty[1].stats ], ], player: [ - [...party[0].stats], - [...party[1].stats], + [ ...party[0].stats ], + [ ...party[1].stats ], ] }; @@ -264,7 +264,7 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { game.move.select(fusionBolt.id, 1, BattlerIndex.PLAYER); // Force first enemy to act in between party - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); expect((game.scene.getCurrentPhase() as MoveEffectPhase).move.moveId).toBe(fusionBolt.id); diff --git a/src/test/moves/gastro_acid.test.ts b/src/test/moves/gastro_acid.test.ts index 60b2bd80c05..fdd75b90b13 100644 --- a/src/test/moves/gastro_acid.test.ts +++ b/src/test/moves/gastro_acid.test.ts @@ -7,7 +7,6 @@ import GameManager from "#test/utils/gameManager"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Moves - Gastro Acid", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -28,7 +27,7 @@ describe("Moves - Gastro Acid", () => { game.override.startingLevel(1); game.override.enemyLevel(100); game.override.ability(Abilities.NONE); - game.override.moveset([Moves.GASTRO_ACID, Moves.WATER_GUN, Moves.SPLASH, Moves.CORE_ENFORCER]); + game.override.moveset([ Moves.GASTRO_ACID, Moves.WATER_GUN, Moves.SPLASH, Moves.CORE_ENFORCER ]); game.override.enemySpecies(Species.BIDOOF); game.override.enemyMoveset(Moves.SPLASH); game.override.enemyAbility(Abilities.WATER_ABSORB); @@ -69,7 +68,7 @@ describe("Moves - Gastro Acid", () => { game.move.select(Moves.CORE_ENFORCER); // Force player to be slower to enable Core Enforcer to proc its suppression effect - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnInitPhase"); diff --git a/src/test/moves/gigaton_hammer.test.ts b/src/test/moves/gigaton_hammer.test.ts index b0ab06fdeb5..f54700fe660 100644 --- a/src/test/moves/gigaton_hammer.test.ts +++ b/src/test/moves/gigaton_hammer.test.ts @@ -25,7 +25,7 @@ describe("Moves - Gigaton Hammer", () => { .battleType("single") .enemySpecies(Species.MAGIKARP) .starterSpecies(Species.FEEBAS) - .moveset([Moves.GIGATON_HAMMER]) + .moveset([ Moves.GIGATON_HAMMER ]) .startingLevel(10) .enemyLevel(100) .enemyMoveset(Moves.SPLASH) @@ -38,7 +38,7 @@ describe("Moves - Gigaton Hammer", () => { const enemy1 = game.scene.getEnemyPokemon()!; game.move.select(Moves.GIGATON_HAMMER); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy1.hp).toBeLessThan(enemy1.getMaxHp()); @@ -61,7 +61,7 @@ describe("Moves - Gigaton Hammer", () => { const enemy1 = game.scene.getEnemyPokemon()!; game.move.select(Moves.GIGATON_HAMMER); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy1.hp).toBeLessThan(enemy1.getMaxHp()); diff --git a/src/test/moves/glaive_rush.test.ts b/src/test/moves/glaive_rush.test.ts index 1a524b4aef6..b36c3e20c7a 100644 --- a/src/test/moves/glaive_rush.test.ts +++ b/src/test/moves/glaive_rush.test.ts @@ -7,7 +7,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Moves - Glaive Rush", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -29,10 +28,10 @@ describe("Moves - Glaive Rush", () => { .disableCrits() .enemySpecies(Species.MAGIKARP) .enemyAbility(Abilities.BALL_FETCH) - .enemyMoveset([Moves.GLAIVE_RUSH]) + .enemyMoveset([ Moves.GLAIVE_RUSH ]) .starterSpecies(Species.KLINK) .ability(Abilities.BALL_FETCH) - .moveset([Moves.SHADOW_SNEAK, Moves.AVALANCHE, Moves.SPLASH, Moves.GLAIVE_RUSH]); + .moveset([ Moves.SHADOW_SNEAK, Moves.AVALANCHE, Moves.SPLASH, Moves.GLAIVE_RUSH ]); }); it("takes double damage from attacks", async () => { @@ -67,7 +66,7 @@ describe("Moves - Glaive Rush", () => { it("interacts properly with multi-lens", async () => { game.override .startingHeldItems([{ name: "MULTI_LENS", count: 2 }]) - .enemyMoveset([Moves.AVALANCHE]); + .enemyMoveset([ Moves.AVALANCHE ]); await game.classicMode.startBattle(); const player = game.scene.getPlayerPokemon()!; @@ -88,7 +87,7 @@ describe("Moves - Glaive Rush", () => { }); it("secondary effects only last until next move", async () => { - game.override.enemyMoveset([Moves.SHADOW_SNEAK]); + game.override.enemyMoveset([ Moves.SHADOW_SNEAK ]); await game.classicMode.startBattle(); const player = game.scene.getPlayerPokemon()!; @@ -115,9 +114,9 @@ describe("Moves - Glaive Rush", () => { it("secondary effects are removed upon switching", async () => { game.override - .enemyMoveset([Moves.SHADOW_SNEAK]) + .enemyMoveset([ Moves.SHADOW_SNEAK ]) .starterSpecies(0); - await game.classicMode.startBattle([Species.KLINK, Species.FEEBAS]); + await game.classicMode.startBattle([ Species.KLINK, Species.FEEBAS ]); const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; @@ -138,7 +137,7 @@ describe("Moves - Glaive Rush", () => { }); it("secondary effects don't activate if move fails", async () => { - game.override.moveset([Moves.SHADOW_SNEAK, Moves.PROTECT, Moves.SPLASH, Moves.GLAIVE_RUSH]); + game.override.moveset([ Moves.SHADOW_SNEAK, Moves.PROTECT, Moves.SPLASH, Moves.GLAIVE_RUSH ]); await game.classicMode.startBattle(); const player = game.scene.getPlayerPokemon()!; @@ -152,7 +151,7 @@ describe("Moves - Glaive Rush", () => { game.move.select(Moves.SHADOW_SNEAK); await game.phaseInterceptor.to("TurnEndPhase"); - game.override.enemyMoveset([Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH ]); const damagedHP1 = 1000 - enemy.hp; enemy.hp = 1000; diff --git a/src/test/moves/guard_split.test.ts b/src/test/moves/guard_split.test.ts index 36be82ba5e4..519f347b920 100644 --- a/src/test/moves/guard_split.test.ts +++ b/src/test/moves/guard_split.test.ts @@ -55,7 +55,7 @@ describe("Moves - Guard Split", () => { }, 20000); it("should be idempotent", async () => { - game.override.enemyMoveset([Moves.GUARD_SPLIT]); + game.override.enemyMoveset([ Moves.GUARD_SPLIT ]); await game.startBattle([ Species.INDEEDEE ]); diff --git a/src/test/moves/hard_press.test.ts b/src/test/moves/hard_press.test.ts index 5d2e4e5b145..0fa4181491c 100644 --- a/src/test/moves/hard_press.test.ts +++ b/src/test/moves/hard_press.test.ts @@ -30,12 +30,12 @@ describe("Moves - Hard Press", () => { game.override.enemySpecies(Species.MUNCHLAX); game.override.enemyAbility(Abilities.BALL_FETCH); game.override.enemyMoveset(Moves.SPLASH); - game.override.moveset([Moves.HARD_PRESS]); + game.override.moveset([ Moves.HARD_PRESS ]); vi.spyOn(moveToCheck, "calculateBattlePower"); }); it("should return 100 power if target HP ratio is at 100%", async () => { - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); game.move.select(Moves.HARD_PRESS); await game.phaseInterceptor.to(MoveEffectPhase); @@ -44,7 +44,7 @@ describe("Moves - Hard Press", () => { }); it("should return 50 power if target HP ratio is at 50%", async () => { - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); const targetHpRatio = .5; const enemy = game.scene.getEnemyPokemon()!; @@ -57,7 +57,7 @@ describe("Moves - Hard Press", () => { }); it("should return 1 power if target HP ratio is at 1%", async () => { - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); const targetHpRatio = .01; const enemy = game.scene.getEnemyPokemon()!; @@ -70,7 +70,7 @@ describe("Moves - Hard Press", () => { }); it("should return 1 power if target HP ratio is less than 1%", async () => { - await game.startBattle([Species.PIKACHU]); + await game.startBattle([ Species.PIKACHU ]); const targetHpRatio = .005; const enemy = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/haze.test.ts b/src/test/moves/haze.test.ts index e5474801899..30aab8bd98c 100644 --- a/src/test/moves/haze.test.ts +++ b/src/test/moves/haze.test.ts @@ -31,12 +31,12 @@ describe("Moves - Haze", () => { game.override.enemyAbility(Abilities.NONE); game.override.startingLevel(100); - game.override.moveset([Moves.HAZE, Moves.SWORDS_DANCE, Moves.CHARM, Moves.SPLASH]); + game.override.moveset([ Moves.HAZE, Moves.SWORDS_DANCE, Moves.CHARM, Moves.SPLASH ]); game.override.ability(Abilities.NONE); }); it("should reset all stat changes of all Pokemon on field", async () => { - await game.startBattle([Species.RATTATA]); + await game.startBattle([ Species.RATTATA ]); const user = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/heal_bell.test.ts b/src/test/moves/heal_bell.test.ts index 1421809cf6c..e4a019d9c0e 100644 --- a/src/test/moves/heal_bell.test.ts +++ b/src/test/moves/heal_bell.test.ts @@ -24,7 +24,7 @@ describe("Moves - Heal Bell", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.HEAL_BELL, Moves.SPLASH]) + .moveset([ Moves.HEAL_BELL, Moves.SPLASH ]) .statusEffect(StatusEffect.BURN) .battleType("double") .enemyAbility(Abilities.BALL_FETCH) @@ -32,8 +32,8 @@ describe("Moves - Heal Bell", () => { }); it("should cure status effect of the user, its ally, and all party pokemon", async () => { - await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA, Species.RATTATA]); - const [leftPlayer, rightPlayer, partyPokemon] = game.scene.getParty(); + await game.classicMode.startBattle([ Species.RATTATA, Species.RATTATA, Species.RATTATA ]); + const [ leftPlayer, rightPlayer, partyPokemon ] = game.scene.getParty(); vi.spyOn(leftPlayer, "resetStatus"); vi.spyOn(rightPlayer, "resetStatus"); @@ -55,8 +55,8 @@ describe("Moves - Heal Bell", () => { it("should not cure status effect of the target/target's allies", async () => { game.override.enemyStatusEffect(StatusEffect.BURN); - await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA]); - const [leftOpp, rightOpp] = game.scene.getEnemyField(); + await game.classicMode.startBattle([ Species.RATTATA, Species.RATTATA ]); + const [ leftOpp, rightOpp ] = game.scene.getEnemyField(); vi.spyOn(leftOpp, "resetStatus"); vi.spyOn(rightOpp, "resetStatus"); @@ -78,8 +78,8 @@ describe("Moves - Heal Bell", () => { it("should not cure status effect of allies ON FIELD with Soundproof, should still cure allies in party", async () => { game.override.ability(Abilities.SOUNDPROOF); - await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA, Species.RATTATA]); - const [leftPlayer, rightPlayer, partyPokemon] = game.scene.getParty(); + await game.classicMode.startBattle([ Species.RATTATA, Species.RATTATA, Species.RATTATA ]); + const [ leftPlayer, rightPlayer, partyPokemon ] = game.scene.getParty(); vi.spyOn(leftPlayer, "resetStatus"); vi.spyOn(rightPlayer, "resetStatus"); diff --git a/src/test/moves/heal_block.test.ts b/src/test/moves/heal_block.test.ts index 14662ac3fce..252533215a8 100644 --- a/src/test/moves/heal_block.test.ts +++ b/src/test/moves/heal_block.test.ts @@ -28,7 +28,7 @@ describe("Moves - Heal Block", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.ABSORB, Moves.WISH, Moves.SPLASH, Moves.AQUA_RING]) + .moveset([ Moves.ABSORB, Moves.WISH, Moves.SPLASH, Moves.AQUA_RING ]) .enemyMoveset(Moves.HEAL_BLOCK) .ability(Abilities.NO_GUARD) .enemyAbility(Abilities.BALL_FETCH) @@ -38,7 +38,7 @@ describe("Moves - Heal Block", () => { it("shouldn't stop damage from HP-drain attacks, just HP restoration", async() => { - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; @@ -46,7 +46,7 @@ describe("Moves - Heal Block", () => { player.damageAndUpdate(enemy.getMaxHp() - 1); game.move.select(Moves.ABSORB); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase"); expect(player.hp).toBe(1); @@ -56,13 +56,13 @@ describe("Moves - Heal Block", () => { it("shouldn't stop Liquid Ooze from dealing damage", async() => { game.override.enemyAbility(Abilities.LIQUID_OOZE); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const player = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; game.move.select(Moves.ABSORB); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("TurnEndPhase"); expect(player.isFullHp()).toBe(false); @@ -70,7 +70,7 @@ describe("Moves - Heal Block", () => { }); it("should stop delayed heals, such as from Wish", async() => { - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const player = game.scene.getPlayerPokemon()!; @@ -91,7 +91,7 @@ describe("Moves - Heal Block", () => { it("should prevent Grassy Terrain from restoring HP", async() => { game.override.enemyAbility(Abilities.GRASSY_SURGE); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const player = game.scene.getPlayerPokemon()!; @@ -104,7 +104,7 @@ describe("Moves - Heal Block", () => { }); it("should prevent healing from heal-over-time moves", async() => { - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const player = game.scene.getPlayerPokemon()!; @@ -122,7 +122,7 @@ describe("Moves - Heal Block", () => { .weather(WeatherType.RAIN) .ability(Abilities.RAIN_DISH); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const player = game.scene.getPlayerPokemon()!; @@ -135,9 +135,9 @@ describe("Moves - Heal Block", () => { }); it("should stop healing from items", async() => { - game.override.startingHeldItems([{name: "LEFTOVERS"}]); + game.override.startingHeldItems([{ name: "LEFTOVERS" }]); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const player = game.scene.getPlayerPokemon()!; player.damageAndUpdate(player.getMaxHp() - 1); diff --git a/src/test/moves/hyper_beam.test.ts b/src/test/moves/hyper_beam.test.ts index a6a471569ed..af8440a0911 100644 --- a/src/test/moves/hyper_beam.test.ts +++ b/src/test/moves/hyper_beam.test.ts @@ -30,17 +30,17 @@ describe("Moves - Hyper Beam", () => { game.override.ability(Abilities.BALL_FETCH); game.override.enemySpecies(Species.SNORLAX); game.override.enemyAbility(Abilities.BALL_FETCH); - game.override.enemyMoveset([Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH ]); game.override.enemyLevel(100); - game.override.moveset([Moves.HYPER_BEAM, Moves.TACKLE]); + game.override.moveset([ Moves.HYPER_BEAM, Moves.TACKLE ]); vi.spyOn(allMoves[Moves.HYPER_BEAM], "accuracy", "get").mockReturnValue(100); }); it( "should force the user to recharge on the next turn (and only that turn)", async () => { - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/imprison.test.ts b/src/test/moves/imprison.test.ts index abb4b3cac6c..f10e20dab63 100644 --- a/src/test/moves/imprison.test.ts +++ b/src/test/moves/imprison.test.ts @@ -25,13 +25,13 @@ describe("Moves - Imprison", () => { game.override .battleType("single") .enemyAbility(Abilities.BALL_FETCH) - .enemyMoveset([Moves.IMPRISON, Moves.SPLASH, Moves.GROWL]) + .enemyMoveset([ Moves.IMPRISON, Moves.SPLASH, Moves.GROWL ]) .enemySpecies(Species.SHUCKLE) - .moveset([Moves.TRANSFORM, Moves.SPLASH]); + .moveset([ Moves.TRANSFORM, Moves.SPLASH ]); }); it("Pokemon under Imprison cannot use shared moves", async () => { - await game.classicMode.startBattle([Species.REGIELEKI]); + await game.classicMode.startBattle([ Species.REGIELEKI ]); const playerPokemon = game.scene.getPlayerPokemon()!; @@ -55,7 +55,7 @@ describe("Moves - Imprison", () => { }); it("Imprison applies to Pokemon switched into Battle", async () => { - await game.classicMode.startBattle([Species.REGIELEKI, Species.BULBASAUR]); + await game.classicMode.startBattle([ Species.REGIELEKI, Species.BULBASAUR ]); const playerPokemon1 = game.scene.getPlayerPokemon()!; @@ -78,8 +78,8 @@ describe("Moves - Imprison", () => { }); it("The effects of Imprison only end when the source is no longer active", async () => { - game.override.moveset([Moves.SPLASH, Moves.IMPRISON]); - await game.classicMode.startBattle([Species.REGIELEKI, Species.BULBASAUR]); + game.override.moveset([ Moves.SPLASH, Moves.IMPRISON ]); + await game.classicMode.startBattle([ Species.REGIELEKI, Species.BULBASAUR ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/jaw_lock.test.ts b/src/test/moves/jaw_lock.test.ts index 3398ec00b3b..30dbcac64a8 100644 --- a/src/test/moves/jaw_lock.test.ts +++ b/src/test/moves/jaw_lock.test.ts @@ -12,7 +12,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Moves - Jaw Lock", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -35,7 +34,7 @@ describe("Moves - Jaw Lock", () => { .enemySpecies(Species.SNORLAX) .enemyAbility(Abilities.INSOMNIA) .enemyMoveset(Moves.SPLASH) - .moveset([Moves.JAW_LOCK, Moves.SPLASH]) + .moveset([ Moves.JAW_LOCK, Moves.SPLASH ]) .startingLevel(100) .enemyLevel(100) .disableCrits(); @@ -44,13 +43,13 @@ describe("Moves - Jaw Lock", () => { it( "should trap the move's user and target", async () => { - await game.startBattle([Species.BULBASAUR]); + await game.startBattle([ Species.BULBASAUR ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.JAW_LOCK); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -68,13 +67,13 @@ describe("Moves - Jaw Lock", () => { "should not trap either pokemon if the target faints", async () => { game.override.enemyLevel(1); - await game.startBattle([Species.BULBASAUR]); + await game.startBattle([ Species.BULBASAUR ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.JAW_LOCK); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase, false); @@ -96,13 +95,13 @@ describe("Moves - Jaw Lock", () => { it( "should only trap the user until the target faints", async () => { - await game.startBattle([Species.BULBASAUR]); + await game.startBattle([ Species.BULBASAUR ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.JAW_LOCK); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); @@ -122,14 +121,14 @@ describe("Moves - Jaw Lock", () => { async () => { game.override.battleType("double"); - await game.startBattle([Species.CHARMANDER, Species.BULBASAUR]); + await game.startBattle([ Species.CHARMANDER, Species.BULBASAUR ]); const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); game.move.select(Moves.JAW_LOCK, 0, BattlerIndex.ENEMY); game.move.select(Moves.SPLASH, 1); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to(MoveEffectPhase); @@ -152,9 +151,9 @@ describe("Moves - Jaw Lock", () => { it( "should not trap either pokemon if the target is protected", async () => { - game.override.enemyMoveset([Moves.PROTECT]); + game.override.enemyMoveset([ Moves.PROTECT ]); - await game.startBattle([Species.BULBASAUR]); + await game.startBattle([ Species.BULBASAUR ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/lash_out.test.ts b/src/test/moves/lash_out.test.ts index 7a8ab6c5bb6..014c0ae8fe5 100644 --- a/src/test/moves/lash_out.test.ts +++ b/src/test/moves/lash_out.test.ts @@ -8,7 +8,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; - describe("Moves - Lash Out", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -30,12 +29,12 @@ describe("Moves - Lash Out", () => { .disableCrits() .enemySpecies(Species.MAGIKARP) .enemyAbility(Abilities.FUR_COAT) - .enemyMoveset([Moves.GROWL]) + .enemyMoveset([ Moves.GROWL ]) .startingLevel(10) .enemyLevel(10) .starterSpecies(Species.FEEBAS) .ability(Abilities.BALL_FETCH) - .moveset([Moves.LASH_OUT]); + .moveset([ Moves.LASH_OUT ]); }); @@ -44,7 +43,7 @@ describe("Moves - Lash Out", () => { await game.classicMode.startBattle(); game.move.select(Moves.LASH_OUT); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase"); expect(allMoves[Moves.LASH_OUT].calculateBattlePower).toHaveReturnedWith(150); diff --git a/src/test/moves/light_screen.test.ts b/src/test/moves/light_screen.test.ts index e94dc4a299e..11b8144bb4e 100644 --- a/src/test/moves/light_screen.test.ts +++ b/src/test/moves/light_screen.test.ts @@ -32,16 +32,16 @@ describe("Moves - Light Screen", () => { game = new GameManager(phaserGame); game.override.battleType("single"); game.override.ability(Abilities.NONE); - game.override.moveset([Moves.ABSORB, Moves.DAZZLING_GLEAM, Moves.TACKLE]); + game.override.moveset([ Moves.ABSORB, Moves.DAZZLING_GLEAM, Moves.TACKLE ]); game.override.enemyLevel(100); game.override.enemySpecies(Species.MAGIKARP); - game.override.enemyMoveset([Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN]); + game.override.enemyMoveset([ Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN, Moves.LIGHT_SCREEN ]); game.override.disableCrits(); }); it("reduces damage of special attacks by half in a single battle", async () => { const moveToUse = Moves.ABSORB; - await game.startBattle([Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE ]); game.move.select(moveToUse); @@ -56,7 +56,7 @@ describe("Moves - Light Screen", () => { game.override.battleType("double"); const moveToUse = Moves.DAZZLING_GLEAM; - await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE, Species.SHUCKLE ]); game.move.select(moveToUse); game.move.select(moveToUse, 1); @@ -69,7 +69,7 @@ describe("Moves - Light Screen", () => { it("does not affect physical attacks", async () => { const moveToUse = Moves.TACKLE; - await game.startBattle([Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE ]); game.move.select(moveToUse); @@ -94,7 +94,7 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) = const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; if (defender.scene.arena.getTagOnSide(ArenaTagType.LIGHT_SCREEN, side)) { - defender.scene.arena.applyTagsForSide(ArenaTagType.LIGHT_SCREEN, side, move.category, defender.scene.currentBattle.double, multiplierHolder); + defender.scene.arena.applyTagsForSide(ArenaTagType.LIGHT_SCREEN, side, false, move.category, multiplierHolder); } return move.power * multiplierHolder.value; diff --git a/src/test/moves/lucky_chant.test.ts b/src/test/moves/lucky_chant.test.ts index 77ea751aee1..02e9dd24465 100644 --- a/src/test/moves/lucky_chant.test.ts +++ b/src/test/moves/lucky_chant.test.ts @@ -8,7 +8,6 @@ import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import GameManager from "../utils/gameManager"; - describe("Moves - Lucky Chant", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -28,10 +27,10 @@ describe("Moves - Lucky Chant", () => { game.override .battleType("single") - .moveset([Moves.LUCKY_CHANT, Moves.SPLASH, Moves.FOLLOW_ME]) + .moveset([ Moves.LUCKY_CHANT, Moves.SPLASH, Moves.FOLLOW_ME ]) .enemySpecies(Species.SNORLAX) .enemyAbility(Abilities.INSOMNIA) - .enemyMoveset([Moves.FLOWER_TRICK]) + .enemyMoveset([ Moves.FLOWER_TRICK ]) .startingLevel(100) .enemyLevel(100); }); @@ -39,7 +38,7 @@ describe("Moves - Lucky Chant", () => { it( "should prevent critical hits from moves", async () => { - await game.startBattle([Species.CHARIZARD]); + await game.startBattle([ Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerPokemon()!; @@ -63,7 +62,7 @@ describe("Moves - Lucky Chant", () => { async () => { game.override.battleType("double"); - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerField(); @@ -87,9 +86,9 @@ describe("Moves - Lucky Chant", () => { it( "should prevent critical hits from field effects", async () => { - game.override.enemyMoveset([Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE ]); - await game.startBattle([Species.CHARIZARD]); + await game.startBattle([ Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/lunar_blessing.test.ts b/src/test/moves/lunar_blessing.test.ts index 6a104762f4d..52c41a30e11 100644 --- a/src/test/moves/lunar_blessing.test.ts +++ b/src/test/moves/lunar_blessing.test.ts @@ -28,13 +28,13 @@ describe("Moves - Lunar Blessing", () => { game.override.enemyMoveset(Moves.SPLASH); game.override.enemyAbility(Abilities.BALL_FETCH); - game.override.moveset([Moves.LUNAR_BLESSING, Moves.SPLASH]); + game.override.moveset([ Moves.LUNAR_BLESSING, Moves.SPLASH ]); game.override.ability(Abilities.BALL_FETCH); }); it("should restore 25% HP of the user and its ally", async () => { - await game.startBattle([Species.RATTATA, Species.RATTATA]); - const [leftPlayer, rightPlayer] = game.scene.getPlayerField(); + await game.startBattle([ Species.RATTATA, Species.RATTATA ]); + const [ leftPlayer, rightPlayer ] = game.scene.getPlayerField(); vi.spyOn(leftPlayer, "getMaxHp").mockReturnValue(100); vi.spyOn(rightPlayer, "getMaxHp").mockReturnValue(100); @@ -62,8 +62,8 @@ describe("Moves - Lunar Blessing", () => { it("should cure status effect of the user and its ally", async () => { game.override.statusEffect(StatusEffect.BURN); - await game.startBattle([Species.RATTATA, Species.RATTATA]); - const [leftPlayer, rightPlayer] = game.scene.getPlayerField(); + await game.startBattle([ Species.RATTATA, Species.RATTATA ]); + const [ leftPlayer, rightPlayer ] = game.scene.getPlayerField(); vi.spyOn(leftPlayer, "resetStatus"); vi.spyOn(rightPlayer, "resetStatus"); diff --git a/src/test/moves/magnet_rise.test.ts b/src/test/moves/magnet_rise.test.ts index 9037e377090..0afcad67ea3 100644 --- a/src/test/moves/magnet_rise.test.ts +++ b/src/test/moves/magnet_rise.test.ts @@ -26,10 +26,10 @@ describe("Moves - Magnet Rise", () => { game.override.battleType("single"); game.override.starterSpecies(Species.MAGNEZONE); game.override.enemySpecies(Species.RATTATA); - game.override.enemyMoveset([Moves.DRILL_RUN, Moves.DRILL_RUN, Moves.DRILL_RUN, Moves.DRILL_RUN]); + game.override.enemyMoveset([ Moves.DRILL_RUN, Moves.DRILL_RUN, Moves.DRILL_RUN, Moves.DRILL_RUN ]); game.override.disableCrits(); game.override.enemyLevel(1); - game.override.moveset([moveToUse, Moves.SPLASH, Moves.GRAVITY, Moves.BATON_PASS]); + game.override.moveset([ moveToUse, Moves.SPLASH, Moves.GRAVITY, Moves.BATON_PASS ]); }); it("MAGNET RISE", async () => { diff --git a/src/test/moves/make_it_rain.test.ts b/src/test/moves/make_it_rain.test.ts index 2b28a958ff0..08021227e9c 100644 --- a/src/test/moves/make_it_rain.test.ts +++ b/src/test/moves/make_it_rain.test.ts @@ -9,7 +9,6 @@ import { MoveEndPhase } from "#app/phases/move-end-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; - describe("Moves - Make It Rain", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -27,7 +26,7 @@ describe("Moves - Make It Rain", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("double"); - game.override.moveset([Moves.MAKE_IT_RAIN, Moves.SPLASH]); + game.override.moveset([ Moves.MAKE_IT_RAIN, Moves.SPLASH ]); game.override.enemySpecies(Species.SNORLAX); game.override.enemyAbility(Abilities.INSOMNIA); game.override.enemyMoveset(Moves.SPLASH); @@ -36,7 +35,7 @@ describe("Moves - Make It Rain", () => { }); it("should only lower SPATK stat stage by 1 once in a double battle", async () => { - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerPokemon()!; @@ -52,7 +51,7 @@ describe("Moves - Make It Rain", () => { game.override.enemyLevel(1); // ensures the enemy will faint game.override.battleType("single"); - await game.startBattle([Species.CHARIZARD]); + await game.startBattle([ Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -68,7 +67,7 @@ describe("Moves - Make It Rain", () => { it("should reduce Sp. Atk. once after KOing two enemies", async () => { game.override.enemyLevel(1); // ensures the enemy will faint - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyField(); @@ -83,7 +82,7 @@ describe("Moves - Make It Rain", () => { }); it("should lower SPATK stat stage by 1 if it only hits the second target", async () => { - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/mat_block.test.ts b/src/test/moves/mat_block.test.ts index 0746f9bcfa9..a4d9177cbdc 100644 --- a/src/test/moves/mat_block.test.ts +++ b/src/test/moves/mat_block.test.ts @@ -10,7 +10,6 @@ import { CommandPhase } from "#app/phases/command-phase"; import { TurnEndPhase } from "#app/phases/turn-end-phase"; - describe("Moves - Mat Block", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -30,10 +29,10 @@ describe("Moves - Mat Block", () => { game.override.battleType("double"); - game.override.moveset([Moves.MAT_BLOCK, Moves.SPLASH]); + game.override.moveset([ Moves.MAT_BLOCK, Moves.SPLASH ]); game.override.enemySpecies(Species.SNORLAX); - game.override.enemyMoveset([Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE ]); game.override.enemyAbility(Abilities.INSOMNIA); game.override.startingLevel(100); @@ -43,7 +42,7 @@ describe("Moves - Mat Block", () => { test( "should protect the user and allies from attack moves", async () => { - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerField(); @@ -62,9 +61,9 @@ describe("Moves - Mat Block", () => { test( "should not protect the user and allies from status moves", async () => { - game.override.enemyMoveset([Moves.GROWL]); + game.override.enemyMoveset([ Moves.GROWL ]); - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerField(); @@ -83,7 +82,7 @@ describe("Moves - Mat Block", () => { test( "should fail when used after the first turn", async () => { - await game.startBattle([Species.BLASTOISE, Species.CHARIZARD]); + await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerField(); diff --git a/src/test/moves/metal_burst.test.ts b/src/test/moves/metal_burst.test.ts new file mode 100644 index 00000000000..3b32dd322a3 --- /dev/null +++ b/src/test/moves/metal_burst.test.ts @@ -0,0 +1,80 @@ +import { BattlerIndex } from "#app/battle"; +import { MoveResult } from "#app/field/pokemon"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Moves - Metal Burst", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([ Moves.METAL_BURST, Moves.FISSURE, Moves.PRECIPICE_BLADES ]) + .ability(Abilities.PURE_POWER) + .startingLevel(10) + .battleType("double") + .disableCrits() + .enemySpecies(Species.PICHU) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.TACKLE); + }); + + it("should redirect target if intended target faints", async () => { + await game.classicMode.startBattle([ Species.FEEBAS, Species.FEEBAS ]); + + const [ , enemy2 ] = game.scene.getEnemyField(); + + game.move.select(Moves.METAL_BURST); + game.move.select(Moves.FISSURE, 1, BattlerIndex.ENEMY); + + await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER); + await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER_2); + + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2 ]); + + await game.phaseInterceptor.to("MoveEndPhase"); + await game.move.forceHit(); + await game.phaseInterceptor.to("MoveEndPhase"); + await game.phaseInterceptor.to("MoveEndPhase"); + + expect(enemy2.isFullHp()).toBe(false); + }); + + it("should not crash if both opponents faint before the move is used", async () => { + await game.classicMode.startBattle([ Species.FEEBAS, Species.ARCEUS ]); + + const [ enemy1, enemy2 ] = game.scene.getEnemyField(); + + game.move.select(Moves.METAL_BURST); + game.move.select(Moves.PRECIPICE_BLADES, 1); + + await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER); + await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER_2); + + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2 ]); + + await game.phaseInterceptor.to("MoveEndPhase"); + await game.move.forceHit(); + await game.phaseInterceptor.to("MoveEndPhase"); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemy1.isFainted()).toBe(true); + expect(enemy2.isFainted()).toBe(true); + expect(game.scene.getPlayerField()[0].getLastXMoves(1)[0].result).toBe(MoveResult.FAIL); + }); +}); diff --git a/src/test/moves/miracle_eye.test.ts b/src/test/moves/miracle_eye.test.ts index 0528b509c82..70f487de942 100644 --- a/src/test/moves/miracle_eye.test.ts +++ b/src/test/moves/miracle_eye.test.ts @@ -28,7 +28,7 @@ describe("Moves - Miracle Eye", () => { .enemyMoveset(Moves.SPLASH) .enemyLevel(5) .starterSpecies(Species.MAGIKARP) - .moveset([Moves.MIRACLE_EYE, Moves.CONFUSION]); + .moveset([ Moves.MIRACLE_EYE, Moves.CONFUSION ]); }); it("should allow Psychic moves to hit Dark types", async () => { @@ -43,7 +43,7 @@ describe("Moves - Miracle Eye", () => { game.move.select(Moves.MIRACLE_EYE); await game.toNextTurn(); game.move.select(Moves.CONFUSION); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); diff --git a/src/test/moves/multi_target.test.ts b/src/test/moves/multi_target.test.ts index cd69482bd8e..b6836b1dcb9 100644 --- a/src/test/moves/multi_target.test.ts +++ b/src/test/moves/multi_target.test.ts @@ -8,7 +8,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Multi-target damage reduction", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -33,18 +32,18 @@ describe("Multi-target damage reduction", () => { .enemySpecies(Species.POLIWAG) .enemyMoveset(Moves.SPLASH) .enemyAbility(Abilities.BALL_FETCH) - .moveset([Moves.TACKLE, Moves.DAZZLING_GLEAM, Moves.EARTHQUAKE, Moves.SPLASH]) + .moveset([ Moves.TACKLE, Moves.DAZZLING_GLEAM, Moves.EARTHQUAKE, Moves.SPLASH ]) .ability(Abilities.BALL_FETCH); }); it("should reduce d.gleam damage when multiple enemies but not tackle", async () => { - await game.startBattle([Species.MAGIKARP, Species.FEEBAS]); + await game.startBattle([ Species.MAGIKARP, Species.FEEBAS ]); - const [enemy1, enemy2] = game.scene.getEnemyField(); + const [ enemy1, enemy2 ] = game.scene.getEnemyField(); game.move.select(Moves.DAZZLING_GLEAM); game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("MoveEndPhase"); const gleam1 = enemy1.getMaxHp() - enemy1.hp; @@ -60,7 +59,7 @@ describe("Multi-target damage reduction", () => { game.move.select(Moves.DAZZLING_GLEAM); game.move.select(Moves.TACKLE, 1, BattlerIndex.ENEMY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); @@ -78,14 +77,14 @@ describe("Multi-target damage reduction", () => { }); it("should reduce earthquake when more than one pokemon other than user is not fainted", async () => { - await game.startBattle([Species.MAGIKARP, Species.FEEBAS]); + await game.startBattle([ Species.MAGIKARP, Species.FEEBAS ]); const player2 = game.scene.getParty()[1]; - const [enemy1, enemy2] = game.scene.getEnemyField(); + const [ enemy1, enemy2 ] = game.scene.getEnemyField(); game.move.select(Moves.EARTHQUAKE); game.move.select(Moves.SPLASH, 1); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("MoveEndPhase"); @@ -100,7 +99,7 @@ describe("Multi-target damage reduction", () => { game.move.select(Moves.EARTHQUAKE); game.move.select(Moves.SPLASH, 1); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); @@ -118,7 +117,7 @@ describe("Multi-target damage reduction", () => { await game.toNextTurn(); game.move.select(Moves.EARTHQUAKE); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); diff --git a/src/test/moves/obstruct.test.ts b/src/test/moves/obstruct.test.ts index 43706a5a1d6..1649c199e32 100644 --- a/src/test/moves/obstruct.test.ts +++ b/src/test/moves/obstruct.test.ts @@ -1,6 +1,7 @@ -import { Moves } from "#app/enums/moves"; -import { Stat } from "#app/enums/stat"; import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { Stat } from "#enums/stat"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -22,13 +23,15 @@ describe("Moves - Obstruct", () => { game = new GameManager(phaserGame); game.override .battleType("single") + .enemySpecies(Species.MAGIKARP) + .enemyMoveset(Moves.TACKLE) .enemyAbility(Abilities.BALL_FETCH) .ability(Abilities.BALL_FETCH) - .moveset([Moves.OBSTRUCT]); + .moveset([ Moves.OBSTRUCT ]) + .starterSpecies(Species.FEEBAS); }); it("protects from contact damaging moves and lowers the opponent's defense by 2 stages", async () => { - game.override.enemyMoveset(Array(4).fill(Moves.ICE_PUNCH)); await game.classicMode.startBattle(); game.move.select(Moves.OBSTRUCT); @@ -42,7 +45,6 @@ describe("Moves - Obstruct", () => { }); it("bypasses accuracy checks when applying protection and defense reduction", async () => { - game.override.enemyMoveset(Array(4).fill(Moves.ICE_PUNCH)); await game.classicMode.startBattle(); game.move.select(Moves.OBSTRUCT); @@ -59,7 +61,7 @@ describe("Moves - Obstruct", () => { ); it("protects from non-contact damaging moves and doesn't lower the opponent's defense by 2 stages", async () => { - game.override.enemyMoveset(Array(4).fill(Moves.WATER_GUN)); + game.override.enemyMoveset(Moves.WATER_GUN); await game.classicMode.startBattle(); game.move.select(Moves.OBSTRUCT); @@ -73,7 +75,7 @@ describe("Moves - Obstruct", () => { }); it("doesn't protect from status moves", async () => { - game.override.enemyMoveset(Array(4).fill(Moves.GROWL)); + game.override.enemyMoveset(Moves.GROWL); await game.classicMode.startBattle(); game.move.select(Moves.OBSTRUCT); @@ -83,4 +85,14 @@ describe("Moves - Obstruct", () => { expect(player.getStatStage(Stat.ATK)).toBe(-1); }); + + it("doesn't reduce the stats of an opponent with Clear Body/etc", async () => { + game.override.enemyAbility(Abilities.CLEAR_BODY); + await game.classicMode.startBattle(); + + game.move.select(Moves.OBSTRUCT); + await game.phaseInterceptor.to("BerryPhase"); + + expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.DEF)).toBe(0); + }); }); diff --git a/src/test/moves/parting_shot.test.ts b/src/test/moves/parting_shot.test.ts index fa328e15a32..e5a2fc38b94 100644 --- a/src/test/moves/parting_shot.test.ts +++ b/src/test/moves/parting_shot.test.ts @@ -11,7 +11,6 @@ import { MessagePhase } from "#app/phases/message-phase"; import { TurnInitPhase } from "#app/phases/turn-init-phase"; - describe("Moves - Parting Shot", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -29,7 +28,7 @@ describe("Moves - Parting Shot", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("single"); - game.override.moveset([Moves.PARTING_SHOT, Moves.SPLASH]); + game.override.moveset([ Moves.PARTING_SHOT, Moves.SPLASH ]); game.override.enemyMoveset(Moves.SPLASH); game.override.startingLevel(5); game.override.enemyLevel(5); @@ -42,7 +41,7 @@ describe("Moves - Parting Shot", () => { game.override .enemySpecies(Species.POOCHYENA) .ability(Abilities.PRANKSTER); - await game.startBattle([Species.MURKROW, Species.MEOWTH]); + await game.startBattle([ Species.MURKROW, Species.MEOWTH ]); const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); @@ -62,7 +61,7 @@ describe("Moves - Parting Shot", () => { game.override .enemySpecies(Species.GHOLDENGO) .enemyAbility(Abilities.GOOD_AS_GOLD); - await game.startBattle([Species.MURKROW, Species.MEOWTH]); + await game.startBattle([ Species.MURKROW, Species.MEOWTH ]); const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); @@ -79,8 +78,8 @@ describe("Moves - Parting Shot", () => { it.skip( // TODO: fix this bug to pass the test! "Parting shot should fail if target is -6/-6 de-buffed", async () => { - game.override.moveset([Moves.PARTING_SHOT, Moves.MEMENTO, Moves.SPLASH]); - await game.startBattle([Species.MEOWTH, Species.MEOWTH, Species.MEOWTH, Species.MURKROW, Species.ABRA]); + game.override.moveset([ Moves.PARTING_SHOT, Moves.MEMENTO, Moves.SPLASH ]); + await game.startBattle([ Species.MEOWTH, Species.MEOWTH, Species.MEOWTH, Species.MURKROW, Species.ABRA ]); // use Memento 3 times to debuff enemy game.move.select(Moves.MEMENTO); @@ -124,8 +123,8 @@ describe("Moves - Parting Shot", () => { game.override .enemySpecies(Species.ALTARIA) .enemyAbility(Abilities.NONE) - .enemyMoveset([Moves.MIST]); - await game.startBattle([Species.SNORLAX, Species.MEOWTH]); + .enemyMoveset([ Moves.MIST ]); + await game.startBattle([ Species.SNORLAX, Species.MEOWTH ]); const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); @@ -145,7 +144,7 @@ describe("Moves - Parting Shot", () => { game.override .enemySpecies(Species.TENTACOOL) .enemyAbility(Abilities.CLEAR_BODY); - await game.startBattle([Species.SNORLAX, Species.MEOWTH]); + await game.startBattle([ Species.SNORLAX, Species.MEOWTH ]); const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); @@ -162,7 +161,7 @@ describe("Moves - Parting Shot", () => { it.skip( // TODO: fix this bug to pass the test! "Parting shot should de-buff and not fail if no party available to switch - party size 1", async () => { - await game.startBattle([Species.MURKROW]); + await game.startBattle([ Species.MURKROW ]); const enemyPokemon = game.scene.getEnemyPokemon()!; expect(enemyPokemon).toBeDefined(); @@ -179,7 +178,7 @@ describe("Moves - Parting Shot", () => { it.skip( // TODO: fix this bug to pass the test! "Parting shot regularly not fail if no party available to switch - party fainted", async () => { - await game.startBattle([Species.MURKROW, Species.MEOWTH]); + await game.startBattle([ Species.MURKROW, Species.MEOWTH ]); game.move.select(Moves.SPLASH); // intentionally kill party pokemon, switch to second slot (now 1 party mon is fainted) diff --git a/src/test/moves/plasma_fists.test.ts b/src/test/moves/plasma_fists.test.ts index a9bd7660dfd..24210cd47fa 100644 --- a/src/test/moves/plasma_fists.test.ts +++ b/src/test/moves/plasma_fists.test.ts @@ -24,7 +24,7 @@ describe("Moves - Plasma Fists", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.PLASMA_FISTS, Moves.TACKLE]) + .moveset([ Moves.PLASMA_FISTS, Moves.TACKLE ]) .battleType("double") .startingLevel(100) .enemySpecies(Species.DUSCLOPS) @@ -34,7 +34,7 @@ describe("Moves - Plasma Fists", () => { }); it("should convert all subsequent Normal-type attacks to Electric-type", async () => { - await game.classicMode.startBattle([Species.DUSCLOPS, Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.DUSCLOPS, Species.BLASTOISE ]); const field = game.scene.getField(true); field.forEach(p => vi.spyOn(p, "getMoveType")); @@ -45,7 +45,7 @@ describe("Moves - Plasma Fists", () => { await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER); await game.forceEnemyMove(Moves.TACKLE, BattlerIndex.PLAYER_2); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("BerryPhase", false); @@ -60,7 +60,7 @@ describe("Moves - Plasma Fists", () => { .battleType("single") .enemyAbility(Abilities.PIXILATE); - await game.classicMode.startBattle([Species.ONIX]); + await game.classicMode.startBattle([ Species.ONIX ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -68,7 +68,7 @@ describe("Moves - Plasma Fists", () => { game.move.select(Moves.PLASMA_FISTS); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.getMoveType).toHaveLastReturnedWith(Type.FAIRY); @@ -81,7 +81,7 @@ describe("Moves - Plasma Fists", () => { .enemyAbility(Abilities.NORMALIZE) .enemyMoveset(Moves.WATER_GUN); - await game.classicMode.startBattle([Species.DUSCLOPS]); + await game.classicMode.startBattle([ Species.DUSCLOPS ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -89,7 +89,7 @@ describe("Moves - Plasma Fists", () => { game.move.select(Moves.PLASMA_FISTS); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.getMoveType).toHaveLastReturnedWith(Type.ELECTRIC); diff --git a/src/test/moves/pledge_moves.test.ts b/src/test/moves/pledge_moves.test.ts new file mode 100644 index 00000000000..93fcf57cc60 --- /dev/null +++ b/src/test/moves/pledge_moves.test.ts @@ -0,0 +1,337 @@ +import { BattlerIndex } from "#app/battle"; +import { allAbilities } from "#app/data/ability"; +import { ArenaTagSide } from "#app/data/arena-tag"; +import { allMoves, FlinchAttr } from "#app/data/move"; +import { Type } from "#app/data/type"; +import { ArenaTagType } from "#enums/arena-tag-type"; +import { Stat } from "#enums/stat"; +import { toDmgValue } from "#app/utils"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; + +describe("Moves - Pledge Moves", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .battleType("double") + .startingLevel(100) + .moveset([ Moves.FIRE_PLEDGE, Moves.GRASS_PLEDGE, Moves.WATER_PLEDGE, Moves.SPLASH ]) + .enemySpecies(Species.SNORLAX) + .enemyLevel(100) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it( + "Fire Pledge - should be an 80-power Fire-type attack outside of combination", + async () => { + await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); + + const firePledge = allMoves[Moves.FIRE_PLEDGE]; + vi.spyOn(firePledge, "calculateBattlePower"); + + const playerPokemon = game.scene.getPlayerField(); + vi.spyOn(playerPokemon[0], "getMoveType"); + + game.move.select(Moves.FIRE_PLEDGE, 0, BattlerIndex.ENEMY); + game.move.select(Moves.SPLASH, 1); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + await game.phaseInterceptor.to("MoveEndPhase", false); + + expect(firePledge.calculateBattlePower).toHaveLastReturnedWith(80); + expect(playerPokemon[0].getMoveType).toHaveLastReturnedWith(Type.FIRE); + } + ); + + it( + "Fire Pledge - should not combine with an ally using Fire Pledge", + async () => { + await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); + + const firePledge = allMoves[Moves.FIRE_PLEDGE]; + vi.spyOn(firePledge, "calculateBattlePower"); + + const playerPokemon = game.scene.getPlayerField(); + playerPokemon.forEach(p => vi.spyOn(p, "getMoveType")); + + const enemyPokemon = game.scene.getEnemyField(); + + game.move.select(Moves.FIRE_PLEDGE, 0, BattlerIndex.ENEMY); + game.move.select(Moves.FIRE_PLEDGE, 0, BattlerIndex.ENEMY_2); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + + await game.phaseInterceptor.to("MoveEndPhase"); + expect(firePledge.calculateBattlePower).toHaveLastReturnedWith(80); + expect(playerPokemon[0].getMoveType).toHaveLastReturnedWith(Type.FIRE); + + await game.phaseInterceptor.to("BerryPhase", false); + expect(firePledge.calculateBattlePower).toHaveLastReturnedWith(80); + expect(playerPokemon[1].getMoveType).toHaveLastReturnedWith(Type.FIRE); + + enemyPokemon.forEach(p => expect(p.hp).toBeLessThan(p.getMaxHp())); + } + ); + + it( + "Fire Pledge - should not combine with an enemy's Pledge move", + async () => { + game.override + .battleType("single") + .enemyMoveset(Moves.GRASS_PLEDGE); + + await game.classicMode.startBattle([ Species.CHARIZARD ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyPokemon = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.FIRE_PLEDGE); + + await game.toNextTurn(); + + // Neither Pokemon should defer their move's effects as they would + // if they combined moves, so both should be damaged. + expect(playerPokemon.hp).toBeLessThan(playerPokemon.getMaxHp()); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); + expect(game.scene.arena.getTag(ArenaTagType.FIRE_GRASS_PLEDGE)).toBeUndefined(); + } + ); + + it( + "Grass Pledge - should combine with Fire Pledge to form a 150-power Fire-type attack that creates a 'sea of fire'", + async () => { + await game.classicMode.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); + + const grassPledge = allMoves[Moves.GRASS_PLEDGE]; + vi.spyOn(grassPledge, "calculateBattlePower"); + + const playerPokemon = game.scene.getPlayerField(); + const enemyPokemon = game.scene.getEnemyField(); + + vi.spyOn(playerPokemon[1], "getMoveType"); + const baseDmgMock = vi.spyOn(enemyPokemon[0], "getBaseDamage"); + + game.move.select(Moves.FIRE_PLEDGE, 0, BattlerIndex.ENEMY_2); + game.move.select(Moves.GRASS_PLEDGE, 1, BattlerIndex.ENEMY); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + // advance to the end of PLAYER_2's move this turn + for (let i = 0; i < 2; i++) { + await game.phaseInterceptor.to("MoveEndPhase"); + } + expect(playerPokemon[1].getMoveType).toHaveLastReturnedWith(Type.FIRE); + expect(grassPledge.calculateBattlePower).toHaveLastReturnedWith(150); + + const baseDmg = baseDmgMock.mock.results[baseDmgMock.mock.results.length - 1].value; + expect(enemyPokemon[0].getMaxHp() - enemyPokemon[0].hp).toBe(toDmgValue(baseDmg * 1.5)); + expect(enemyPokemon[1].hp).toBe(enemyPokemon[1].getMaxHp()); // PLAYER should not have attacked + expect(game.scene.arena.getTagOnSide(ArenaTagType.FIRE_GRASS_PLEDGE, ArenaTagSide.ENEMY)).toBeDefined(); + + const enemyStartingHp = enemyPokemon.map(p => p.hp); + await game.toNextTurn(); + enemyPokemon.forEach((p, i) => expect(enemyStartingHp[i] - p.hp).toBe(toDmgValue(p.getMaxHp() / 8))); + } + ); + + it( + "Fire Pledge - should combine with Water Pledge to form a 150-power Water-type attack that creates a 'rainbow'", + async () => { + game.override.moveset([ Moves.FIRE_PLEDGE, Moves.WATER_PLEDGE, Moves.FIERY_DANCE, Moves.SPLASH ]); + + await game.classicMode.startBattle([ Species.BLASTOISE, Species.VENUSAUR ]); + + const firePledge = allMoves[Moves.FIRE_PLEDGE]; + vi.spyOn(firePledge, "calculateBattlePower"); + + const playerPokemon = game.scene.getPlayerField(); + const enemyPokemon = game.scene.getEnemyField(); + + vi.spyOn(playerPokemon[1], "getMoveType"); + + game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY_2); + game.move.select(Moves.FIRE_PLEDGE, 1, BattlerIndex.ENEMY); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + // advance to the end of PLAYER_2's move this turn + for (let i = 0; i < 2; i++) { + await game.phaseInterceptor.to("MoveEndPhase"); + } + expect(playerPokemon[1].getMoveType).toHaveLastReturnedWith(Type.WATER); + expect(firePledge.calculateBattlePower).toHaveLastReturnedWith(150); + expect(enemyPokemon[1].hp).toBe(enemyPokemon[1].getMaxHp()); // PLAYER should not have attacked + expect(game.scene.arena.getTagOnSide(ArenaTagType.WATER_FIRE_PLEDGE, ArenaTagSide.PLAYER)).toBeDefined(); + + await game.toNextTurn(); + + game.move.select(Moves.FIERY_DANCE, 0, BattlerIndex.ENEMY_2); + game.move.select(Moves.SPLASH, 1); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + await game.phaseInterceptor.to("MoveEndPhase"); + + // Rainbow effect should increase Fiery Dance's chance of raising Sp. Atk to 100% + expect(playerPokemon[0].getStatStage(Stat.SPATK)).toBe(1); + } + ); + + it( + "Water Pledge - should combine with Grass Pledge to form a 150-power Grass-type attack that creates a 'swamp'", + async () => { + await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); + + const waterPledge = allMoves[Moves.WATER_PLEDGE]; + vi.spyOn(waterPledge, "calculateBattlePower"); + + const playerPokemon = game.scene.getPlayerField(); + const enemyPokemon = game.scene.getEnemyField(); + const enemyStartingSpd = enemyPokemon.map(p => p.getEffectiveStat(Stat.SPD)); + + vi.spyOn(playerPokemon[1], "getMoveType"); + + game.move.select(Moves.GRASS_PLEDGE, 0, BattlerIndex.ENEMY_2); + game.move.select(Moves.WATER_PLEDGE, 1, BattlerIndex.ENEMY); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + // advance to the end of PLAYER_2's move this turn + for (let i = 0; i < 2; i++) { + await game.phaseInterceptor.to("MoveEndPhase"); + } + + expect(playerPokemon[1].getMoveType).toHaveLastReturnedWith(Type.GRASS); + expect(waterPledge.calculateBattlePower).toHaveLastReturnedWith(150); + expect(enemyPokemon[1].hp).toBe(enemyPokemon[1].getMaxHp()); + + expect(game.scene.arena.getTagOnSide(ArenaTagType.GRASS_WATER_PLEDGE, ArenaTagSide.ENEMY)).toBeDefined(); + enemyPokemon.forEach((p, i) => expect(p.getEffectiveStat(Stat.SPD)).toBe(Math.floor(enemyStartingSpd[i] / 4))); + } + ); + + it( + "Pledge Moves - should alter turn order when used in combination", + async () => { + await game.classicMode.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); + + const enemyPokemon = game.scene.getEnemyField(); + + game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY); + game.move.select(Moves.FIRE_PLEDGE, 1, BattlerIndex.ENEMY_2); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2 ]); + // PLAYER_2 should act with a combined move immediately after PLAYER as the second move in the turn + for (let i = 0; i < 2; i++) { + await game.phaseInterceptor.to("MoveEndPhase"); + } + expect(enemyPokemon[0].hp).toBe(enemyPokemon[0].getMaxHp()); + expect(enemyPokemon[1].hp).toBeLessThan(enemyPokemon[1].getMaxHp()); + } + ); + + it( + "Pledge Moves - 'rainbow' effect should not stack with Serene Grace when applied to flinching moves", + async () => { + game.override + .ability(Abilities.SERENE_GRACE) + .moveset([ Moves.FIRE_PLEDGE, Moves.WATER_PLEDGE, Moves.IRON_HEAD, Moves.SPLASH ]); + + await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); + + const ironHeadFlinchAttr = allMoves[Moves.IRON_HEAD].getAttrs(FlinchAttr)[0]; + vi.spyOn(ironHeadFlinchAttr, "getMoveChance"); + + game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY); + game.move.select(Moves.FIRE_PLEDGE, 1, BattlerIndex.ENEMY_2); + + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(game.scene.arena.getTagOnSide(ArenaTagType.WATER_FIRE_PLEDGE, ArenaTagSide.PLAYER)).toBeDefined(); + + game.move.select(Moves.IRON_HEAD, 0, BattlerIndex.ENEMY); + game.move.select(Moves.SPLASH, 1); + + await game.phaseInterceptor.to("BerryPhase", false); + + expect(ironHeadFlinchAttr.getMoveChance).toHaveLastReturnedWith(60); + } + ); + + it( + "Pledge Moves - should have no effect when the second ally's move is cancelled", + async () => { + game.override + .enemyMoveset([ Moves.SPLASH, Moves.SPORE ]); + + await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); + + const enemyPokemon = game.scene.getEnemyField(); + + game.move.select(Moves.FIRE_PLEDGE, 0, BattlerIndex.ENEMY); + game.move.select(Moves.GRASS_PLEDGE, 1, BattlerIndex.ENEMY_2); + + await game.forceEnemyMove(Moves.SPORE, BattlerIndex.PLAYER_2); + await game.forceEnemyMove(Moves.SPLASH); + + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2 ]); + + await game.phaseInterceptor.to("BerryPhase", false); + + enemyPokemon.forEach((p) => expect(p.hp).toBe(p.getMaxHp())); + } + ); + + it( + "Pledge Moves - should ignore redirection from another Pokemon's Storm Drain", + async () => { + await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); + + const enemyPokemon = game.scene.getEnemyField(); + vi.spyOn(enemyPokemon[1], "getAbility").mockReturnValue(allAbilities[Abilities.STORM_DRAIN]); + + game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY); + game.move.select(Moves.SPLASH, 1); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); + + await game.phaseInterceptor.to("MoveEndPhase", false); + + expect(enemyPokemon[0].hp).toBeLessThan(enemyPokemon[0].getMaxHp()); + expect(enemyPokemon[1].getStatStage(Stat.SPATK)).toBe(0); + } + ); + + it( + "Pledge Moves - should not ignore redirection from another Pokemon's Follow Me", + async () => { + game.override.enemyMoveset([ Moves.FOLLOW_ME, Moves.SPLASH ]); + await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); + + game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY); + game.move.select(Moves.SPLASH, 1); + + await game.forceEnemyMove(Moves.SPLASH); + await game.forceEnemyMove(Moves.FOLLOW_ME); + + await game.phaseInterceptor.to("BerryPhase", false); + + const enemyPokemon = game.scene.getEnemyField(); + expect(enemyPokemon[0].hp).toBe(enemyPokemon[0].getMaxHp()); + expect(enemyPokemon[1].hp).toBeLessThan(enemyPokemon[1].getMaxHp()); + } + ); +}); diff --git a/src/test/moves/power_shift.test.ts b/src/test/moves/power_shift.test.ts index f39759f278b..e389f77bedf 100644 --- a/src/test/moves/power_shift.test.ts +++ b/src/test/moves/power_shift.test.ts @@ -22,7 +22,7 @@ describe("Moves - Power Shift", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.POWER_SHIFT, Moves.BULK_UP]) + .moveset([ Moves.POWER_SHIFT, Moves.BULK_UP ]) .battleType("single") .ability(Abilities.BALL_FETCH) .enemyAbility(Abilities.BALL_FETCH) @@ -30,7 +30,7 @@ describe("Moves - Power Shift", () => { }); it("switches the user's raw Attack stat with its raw Defense stat", async () => { - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const playerPokemon = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/power_split.test.ts b/src/test/moves/power_split.test.ts index aaf34541567..914fa86e491 100644 --- a/src/test/moves/power_split.test.ts +++ b/src/test/moves/power_split.test.ts @@ -55,7 +55,7 @@ describe("Moves - Power Split", () => { }, 20000); it("should be idempotent", async () => { - game.override.enemyMoveset([Moves.POWER_SPLIT]); + game.override.enemyMoveset([ Moves.POWER_SPLIT ]); await game.startBattle([ Species.INDEEDEE ]); diff --git a/src/test/moves/power_trick.test.ts b/src/test/moves/power_trick.test.ts new file mode 100644 index 00000000000..a064a43dec4 --- /dev/null +++ b/src/test/moves/power_trick.test.ts @@ -0,0 +1,113 @@ +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import { Moves } from "#enums/moves"; +import { Stat } from "#enums/stat"; +import { Species } from "#enums/species"; +import { TurnEndPhase } from "#app/phases/turn-end-phase"; +import { Abilities } from "#enums/abilities"; +import { BattlerTagType } from "#enums/battler-tag-type"; + +describe("Moves - Power Trick", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .battleType("single") + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH) + .enemySpecies(Species.MEW) + .enemyLevel(200) + .moveset([ Moves.POWER_TRICK ]) + .ability(Abilities.BALL_FETCH); + }); + + it("swaps the user's ATK and DEF stats", async () => { + await game.classicMode.startBattle([ Species.SHUCKLE ]); + + const player = game.scene.getPlayerPokemon()!; + const baseATK = player.getStat(Stat.ATK, false); + const baseDEF = player.getStat(Stat.DEF, false); + + game.move.select(Moves.POWER_TRICK); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(player.getStat(Stat.ATK, false)).toBe(baseDEF); + expect(player.getStat(Stat.DEF, false)).toBe(baseATK); + expect(player.getTag(BattlerTagType.POWER_TRICK)).toBeDefined(); + }); + + it("resets initial ATK and DEF stat swap when used consecutively", async () => { + await game.classicMode.startBattle([ Species.SHUCKLE ]); + + const player = game.scene.getPlayerPokemon()!; + const baseATK = player.getStat(Stat.ATK, false); + const baseDEF = player.getStat(Stat.DEF, false); + + game.move.select(Moves.POWER_TRICK); + + await game.phaseInterceptor.to(TurnEndPhase); + + game.move.select(Moves.POWER_TRICK); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(player.getStat(Stat.ATK, false)).toBe(baseATK); + expect(player.getStat(Stat.DEF, false)).toBe(baseDEF); + expect(player.getTag(BattlerTagType.POWER_TRICK)).toBeUndefined(); + }); + + it("should pass effect when using BATON_PASS", async () => { + await game.classicMode.startBattle([ Species.SHUCKLE, Species.SHUCKLE ]); + await game.override.moveset([ Moves.POWER_TRICK, Moves.BATON_PASS ]); + + const player = game.scene.getPlayerPokemon()!; + player.addTag(BattlerTagType.POWER_TRICK); + + game.move.select(Moves.BATON_PASS); + game.doSelectPartyPokemon(1); + + await game.phaseInterceptor.to(TurnEndPhase); + + const switchedPlayer = game.scene.getPlayerPokemon()!; + const baseATK = switchedPlayer.getStat(Stat.ATK); + const baseDEF = switchedPlayer.getStat(Stat.DEF); + + expect(switchedPlayer.getStat(Stat.ATK, false)).toBe(baseDEF); + expect(switchedPlayer.getStat(Stat.DEF, false)).toBe(baseATK); + expect(switchedPlayer.getTag(BattlerTagType.POWER_TRICK)).toBeDefined(); + }); + + it("should remove effect after using Transform", async () => { + await game.classicMode.startBattle([ Species.SHUCKLE, Species.SHUCKLE ]); + await game.override.moveset([ Moves.POWER_TRICK, Moves.TRANSFORM ]); + + const player = game.scene.getPlayerPokemon()!; + player.addTag(BattlerTagType.POWER_TRICK); + + game.move.select(Moves.TRANSFORM); + + await game.phaseInterceptor.to(TurnEndPhase); + + const enemy = game.scene.getEnemyPokemon()!; + const baseATK = enemy.getStat(Stat.ATK); + const baseDEF = enemy.getStat(Stat.DEF); + + expect(player.getStat(Stat.ATK, false)).toBe(baseATK); + expect(player.getStat(Stat.DEF, false)).toBe(baseDEF); + expect(player.getTag(BattlerTagType.POWER_TRICK)).toBeUndefined(); + }); +}); diff --git a/src/test/moves/protect.test.ts b/src/test/moves/protect.test.ts index dcf4211ac7f..e639969ddf0 100644 --- a/src/test/moves/protect.test.ts +++ b/src/test/moves/protect.test.ts @@ -11,7 +11,6 @@ import { BattlerIndex } from "#app/battle"; import { MoveResult } from "#app/field/pokemon"; - describe("Moves - Protect", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -31,11 +30,11 @@ describe("Moves - Protect", () => { game.override.battleType("single"); - game.override.moveset([Moves.PROTECT]); + game.override.moveset([ Moves.PROTECT ]); game.override.enemySpecies(Species.SNORLAX); game.override.enemyAbility(Abilities.INSOMNIA); - game.override.enemyMoveset([Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE ]); game.override.startingLevel(100); game.override.enemyLevel(100); @@ -44,7 +43,7 @@ describe("Moves - Protect", () => { test( "should protect the user from attacks", async () => { - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -59,10 +58,10 @@ describe("Moves - Protect", () => { test( "should prevent secondary effects from the opponent's attack", async () => { - game.override.enemyMoveset([Moves.CEASELESS_EDGE]); + game.override.enemyMoveset([ Moves.CEASELESS_EDGE ]); vi.spyOn(allMoves[Moves.CEASELESS_EDGE], "accuracy", "get").mockReturnValue(100); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -78,9 +77,9 @@ describe("Moves - Protect", () => { test( "should protect the user from status moves", async () => { - game.override.enemyMoveset([Moves.CHARM]); + game.override.enemyMoveset([ Moves.CHARM ]); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -95,9 +94,9 @@ describe("Moves - Protect", () => { test( "should stop subsequent hits of a multi-hit move", async () => { - game.override.enemyMoveset([Moves.TACHYON_CUTTER]); + game.override.enemyMoveset([ Moves.TACHYON_CUTTER ]); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -114,16 +113,16 @@ describe("Moves - Protect", () => { test( "should fail if the user is the last to move in the turn", async () => { - game.override.enemyMoveset([Moves.PROTECT]); + game.override.enemyMoveset([ Moves.PROTECT ]); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.PROTECT); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase", false); diff --git a/src/test/moves/purify.test.ts b/src/test/moves/purify.test.ts index 3ba9dfcbb65..3b07eafd75a 100644 --- a/src/test/moves/purify.test.ts +++ b/src/test/moves/purify.test.ts @@ -9,7 +9,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - describe("Moves - Purify", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -30,11 +29,11 @@ describe("Moves - Purify", () => { game.override.starterSpecies(Species.PYUKUMUKU); game.override.startingLevel(10); - game.override.moveset([Moves.PURIFY, Moves.SIZZLY_SLIDE]); + game.override.moveset([ Moves.PURIFY, Moves.SIZZLY_SLIDE ]); game.override.enemySpecies(Species.MAGIKARP); game.override.enemyLevel(10); - game.override.enemyMoveset([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE ]); }); test( @@ -49,7 +48,7 @@ describe("Moves - Purify", () => { enemyPokemon.status = new Status(StatusEffect.BURN); game.move.select(Moves.PURIFY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEndPhase); expect(enemyPokemon.status).toBeNull(); @@ -68,7 +67,7 @@ describe("Moves - Purify", () => { const playerInitialHp = playerPokemon.hp; game.move.select(Moves.PURIFY); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEndPhase); expect(playerPokemon.hp).toBe(playerInitialHp); diff --git a/src/test/moves/quick_guard.test.ts b/src/test/moves/quick_guard.test.ts index e03beeac06a..7bda71782aa 100644 --- a/src/test/moves/quick_guard.test.ts +++ b/src/test/moves/quick_guard.test.ts @@ -9,7 +9,6 @@ import { BattlerIndex } from "#app/battle"; import { MoveResult } from "#app/field/pokemon"; - describe("Moves - Quick Guard", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -29,10 +28,10 @@ describe("Moves - Quick Guard", () => { game.override.battleType("double"); - game.override.moveset([Moves.QUICK_GUARD, Moves.SPLASH, Moves.FOLLOW_ME]); + game.override.moveset([ Moves.QUICK_GUARD, Moves.SPLASH, Moves.FOLLOW_ME ]); game.override.enemySpecies(Species.SNORLAX); - game.override.enemyMoveset([Moves.QUICK_ATTACK]); + game.override.enemyMoveset([ Moves.QUICK_ATTACK ]); game.override.enemyAbility(Abilities.INSOMNIA); game.override.startingLevel(100); @@ -42,7 +41,7 @@ describe("Moves - Quick Guard", () => { test( "should protect the user and allies from priority moves", async () => { - await game.classicMode.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerField(); @@ -59,9 +58,9 @@ describe("Moves - Quick Guard", () => { "should protect the user and allies from Prankster-boosted moves", async () => { game.override.enemyAbility(Abilities.PRANKSTER); - game.override.enemyMoveset([Moves.GROWL]); + game.override.enemyMoveset([ Moves.GROWL ]); - await game.classicMode.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerField(); @@ -77,9 +76,9 @@ describe("Moves - Quick Guard", () => { test( "should stop subsequent hits of a multi-hit priority move", async () => { - game.override.enemyMoveset([Moves.WATER_SHURIKEN]); + game.override.enemyMoveset([ Moves.WATER_SHURIKEN ]); - await game.classicMode.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); @@ -98,16 +97,16 @@ describe("Moves - Quick Guard", () => { "should fail if the user is the last to move in the turn", async () => { game.override.battleType("single"); - game.override.enemyMoveset([Moves.QUICK_GUARD]); + game.override.enemyMoveset([ Moves.QUICK_GUARD ]); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.QUICK_GUARD); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase", false); diff --git a/src/test/moves/rage_powder.test.ts b/src/test/moves/rage_powder.test.ts index bb31a1f2194..1b73a7f0f5f 100644 --- a/src/test/moves/rage_powder.test.ts +++ b/src/test/moves/rage_powder.test.ts @@ -7,7 +7,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - describe("Moves - Rage Powder", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -28,14 +27,14 @@ describe("Moves - Rage Powder", () => { game.override.enemySpecies(Species.SNORLAX); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK]); - game.override.enemyMoveset([Moves.RAGE_POWDER, Moves.TACKLE, Moves.SPLASH]); + game.override.moveset([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + game.override.enemyMoveset([ Moves.RAGE_POWDER, Moves.TACKLE, Moves.SPLASH ]); }); test( "move effect should be bypassed by Grass type", async () => { - await game.classicMode.startBattle([Species.AMOONGUSS, Species.VENUSAUR]); + await game.classicMode.startBattle([ Species.AMOONGUSS, Species.VENUSAUR ]); const enemyPokemon = game.scene.getEnemyField(); @@ -59,7 +58,7 @@ describe("Moves - Rage Powder", () => { game.override.ability(Abilities.OVERCOAT); // Test with two non-Grass type player Pokemon - await game.classicMode.startBattle([Species.BLASTOISE, Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); const enemyPokemon = game.scene.getEnemyField(); diff --git a/src/test/moves/reflect.test.ts b/src/test/moves/reflect.test.ts index 9780ede3c55..b18b2423895 100644 --- a/src/test/moves/reflect.test.ts +++ b/src/test/moves/reflect.test.ts @@ -32,16 +32,16 @@ describe("Moves - Reflect", () => { game = new GameManager(phaserGame); game.override.battleType("single"); game.override.ability(Abilities.NONE); - game.override.moveset([Moves.ABSORB, Moves.ROCK_SLIDE, Moves.TACKLE]); + game.override.moveset([ Moves.ABSORB, Moves.ROCK_SLIDE, Moves.TACKLE ]); game.override.enemyLevel(100); game.override.enemySpecies(Species.MAGIKARP); - game.override.enemyMoveset([Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT]); + game.override.enemyMoveset([ Moves.REFLECT, Moves.REFLECT, Moves.REFLECT, Moves.REFLECT ]); game.override.disableCrits(); }); it("reduces damage of physical attacks by half in a single battle", async () => { const moveToUse = Moves.TACKLE; - await game.startBattle([Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE ]); game.move.select(moveToUse); @@ -55,7 +55,7 @@ describe("Moves - Reflect", () => { game.override.battleType("double"); const moveToUse = Moves.ROCK_SLIDE; - await game.startBattle([Species.SHUCKLE, Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE, Species.SHUCKLE ]); game.move.select(moveToUse); game.move.select(moveToUse, 1); @@ -68,7 +68,7 @@ describe("Moves - Reflect", () => { it("does not affect special attacks", async () => { const moveToUse = Moves.ABSORB; - await game.startBattle([Species.SHUCKLE]); + await game.startBattle([ Species.SHUCKLE ]); game.move.select(moveToUse); @@ -94,7 +94,7 @@ const getMockedMoveDamage = (defender: Pokemon, attacker: Pokemon, move: Move) = const side = defender.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; if (defender.scene.arena.getTagOnSide(ArenaTagType.REFLECT, side)) { - defender.scene.arena.applyTagsForSide(ArenaTagType.REFLECT, side, move.category, defender.scene.currentBattle.double, multiplierHolder); + defender.scene.arena.applyTagsForSide(ArenaTagType.REFLECT, side, false, move.category, multiplierHolder); } return move.power * multiplierHolder.value; diff --git a/src/test/moves/relic_song.test.ts b/src/test/moves/relic_song.test.ts index 67fc557a318..eb877b6054d 100644 --- a/src/test/moves/relic_song.test.ts +++ b/src/test/moves/relic_song.test.ts @@ -23,7 +23,7 @@ describe("Moves - Relic Song", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.RELIC_SONG, Moves.SPLASH]) + .moveset([ Moves.RELIC_SONG, Moves.SPLASH ]) .battleType("single") .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH) @@ -32,7 +32,7 @@ describe("Moves - Relic Song", () => { }); it("swaps Meloetta's form between Aria and Pirouette", async () => { - await game.classicMode.startBattle([Species.MELOETTA]); + await game.classicMode.startBattle([ Species.MELOETTA ]); const meloetta = game.scene.getPlayerPokemon()!; @@ -49,7 +49,7 @@ describe("Moves - Relic Song", () => { it("doesn't swap Meloetta's form during a mono-type challenge", async () => { game.challengeMode.addChallenge(Challenges.SINGLE_TYPE, Type.PSYCHIC + 1, 0); - await game.challengeMode.startBattle([Species.MELOETTA]); + await game.challengeMode.startBattle([ Species.MELOETTA ]); const meloetta = game.scene.getPlayerPokemon()!; @@ -64,9 +64,9 @@ describe("Moves - Relic Song", () => { it("doesn't swap Meloetta's form during biome change (arena reset)", async () => { game.override - .starterForms({[Species.MELOETTA]: 1}) + .starterForms({ [Species.MELOETTA]: 1 }) .startingWave(10); - await game.classicMode.startBattle([Species.MELOETTA]); + await game.classicMode.startBattle([ Species.MELOETTA ]); const meloetta = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/retaliate.test.ts b/src/test/moves/retaliate.test.ts index 62965fffba6..e00b9da6010 100644 --- a/src/test/moves/retaliate.test.ts +++ b/src/test/moves/retaliate.test.ts @@ -26,16 +26,16 @@ describe("Moves - Retaliate", () => { game.override .battleType("single") .enemySpecies(Species.SNORLAX) - .enemyMoveset([Moves.RETALIATE, Moves.RETALIATE, Moves.RETALIATE, Moves.RETALIATE]) + .enemyMoveset([ Moves.RETALIATE, Moves.RETALIATE, Moves.RETALIATE, Moves.RETALIATE ]) .enemyLevel(100) - .moveset([Moves.RETALIATE, Moves.SPLASH]) + .moveset([ Moves.RETALIATE, Moves.SPLASH ]) .startingLevel(80) .disableCrits(); }); it("increases power if ally died previous turn", async () => { vi.spyOn(retaliate, "calculateBattlePower"); - await game.startBattle([Species.ABRA, Species.COBALION]); + await game.startBattle([ Species.ABRA, Species.COBALION ]); game.move.select(Moves.RETALIATE); await game.phaseInterceptor.to("TurnEndPhase"); expect(retaliate.calculateBattlePower).toHaveLastReturnedWith(70); diff --git a/src/test/moves/rollout.test.ts b/src/test/moves/rollout.test.ts index c08535a61df..4a14b100f6d 100644 --- a/src/test/moves/rollout.test.ts +++ b/src/test/moves/rollout.test.ts @@ -35,7 +35,7 @@ describe("Moves - Rollout", () => { }); it("should double it's dmg on sequential uses but reset after 5", async () => { - game.override.moveset([Moves.ROLLOUT]); + game.override.moveset([ Moves.ROLLOUT ]); vi.spyOn(allMoves[Moves.ROLLOUT], "accuracy", "get").mockReturnValue(100); //always hit const variance = 5; @@ -45,10 +45,10 @@ describe("Moves - Rollout", () => { await game.startBattle(); const playerPkm = game.scene.getParty()[0]; - vi.spyOn(playerPkm, "stats", "get").mockReturnValue([500000, 1, 1, 1, 1, 1]); // HP, ATK, DEF, SPATK, SPDEF, SPD + vi.spyOn(playerPkm, "stats", "get").mockReturnValue([ 500000, 1, 1, 1, 1, 1 ]); // HP, ATK, DEF, SPATK, SPDEF, SPD const enemyPkm = game.scene.getEnemyParty()[0]; - vi.spyOn(enemyPkm, "stats", "get").mockReturnValue([500000, 1, 1, 1, 1, 1]); // HP, ATK, DEF, SPATK, SPDEF, SPD + vi.spyOn(enemyPkm, "stats", "get").mockReturnValue([ 500000, 1, 1, 1, 1, 1 ]); // HP, ATK, DEF, SPATK, SPDEF, SPD vi.spyOn(enemyPkm, "getHeldItems").mockReturnValue([]); //no berries enemyPkm.hp = enemyPkm.getMaxHp(); @@ -62,7 +62,7 @@ describe("Moves - Rollout", () => { previousHp = enemyPkm.hp; } - const [turn1Dmg, turn2Dmg, turn3Dmg, turn4Dmg, turn5Dmg, turn6Dmg] = dmgHistory; + const [ turn1Dmg, turn2Dmg, turn3Dmg, turn4Dmg, turn5Dmg, turn6Dmg ] = dmgHistory; expect(turn2Dmg).toBeGreaterThanOrEqual(turn1Dmg * 2 - variance); expect(turn2Dmg).toBeLessThanOrEqual(turn1Dmg * 2 + variance); diff --git a/src/test/moves/roost.test.ts b/src/test/moves/roost.test.ts index a1c473c0632..e595f879844 100644 --- a/src/test/moves/roost.test.ts +++ b/src/test/moves/roost.test.ts @@ -10,7 +10,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - describe("Moves - Roost", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -32,7 +31,7 @@ describe("Moves - Roost", () => { game.override.startingLevel(100); game.override.enemyLevel(100); game.override.enemyMoveset(Moves.EARTHQUAKE); - game.override.moveset([Moves.ROOST, Moves.BURN_UP, Moves.DOUBLE_SHOCK]); + game.override.moveset([ Moves.ROOST, Moves.BURN_UP, Moves.DOUBLE_SHOCK ]); }); /** @@ -51,11 +50,11 @@ describe("Moves - Roost", () => { test( "Non flying type uses roost -> no type change, took damage", async () => { - await game.classicMode.startBattle([Species.DUNSPARCE]); + await game.classicMode.startBattle([ Species.DUNSPARCE ]); const playerPokemon = game.scene.getPlayerPokemon()!; const playerPokemonStartingHP = playerPokemon.hp; game.move.select(Moves.ROOST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); // Should only be normal type, and NOT flying type @@ -78,11 +77,11 @@ describe("Moves - Roost", () => { test( "Pure flying type -> becomes normal after roost and takes damage from ground moves -> regains flying", async () => { - await game.classicMode.startBattle([Species.TORNADUS]); + await game.classicMode.startBattle([ Species.TORNADUS ]); const playerPokemon = game.scene.getPlayerPokemon()!; const playerPokemonStartingHP = playerPokemon.hp; game.move.select(Moves.ROOST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); // Should only be normal type, and NOT flying type @@ -106,11 +105,11 @@ describe("Moves - Roost", () => { test( "Dual X/flying type -> becomes type X after roost and takes damage from ground moves -> regains flying", async () => { - await game.classicMode.startBattle([Species.HAWLUCHA]); + await game.classicMode.startBattle([ Species.HAWLUCHA ]); const playerPokemon = game.scene.getPlayerPokemon()!; const playerPokemonStartingHP = playerPokemon.hp; game.move.select(Moves.ROOST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); // Should only be pure fighting type and grounded @@ -135,11 +134,11 @@ describe("Moves - Roost", () => { "Pokemon with levitate after using roost should lose flying type but still be unaffected by ground moves", async () => { game.override.starterForms({ [Species.ROTOM]: 4 }); - await game.classicMode.startBattle([Species.ROTOM]); + await game.classicMode.startBattle([ Species.ROTOM ]); const playerPokemon = game.scene.getPlayerPokemon()!; const playerPokemonStartingHP = playerPokemon.hp; game.move.select(Moves.ROOST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); // Should only be pure eletric type and grounded @@ -163,11 +162,11 @@ describe("Moves - Roost", () => { test( "A fire/flying type that uses burn up, then roost should be typeless until end of turn", async () => { - await game.classicMode.startBattle([Species.MOLTRES]); + await game.classicMode.startBattle([ Species.MOLTRES ]); const playerPokemon = game.scene.getPlayerPokemon()!; const playerPokemonStartingHP = playerPokemon.hp; game.move.select(Moves.BURN_UP); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); // Should only be pure flying type after burn up @@ -177,7 +176,7 @@ describe("Moves - Roost", () => { await game.phaseInterceptor.to(TurnEndPhase); game.move.select(Moves.ROOST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); // Should only be typeless type after roost and is grounded @@ -203,11 +202,11 @@ describe("Moves - Roost", () => { "An electric/flying type that uses double shock, then roost should be typeless until end of turn", async () => { game.override.enemySpecies(Species.ZEKROM); - await game.classicMode.startBattle([Species.ZAPDOS]); + await game.classicMode.startBattle([ Species.ZAPDOS ]); const playerPokemon = game.scene.getPlayerPokemon()!; const playerPokemonStartingHP = playerPokemon.hp; game.move.select(Moves.DOUBLE_SHOCK); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); // Should only be pure flying type after burn up @@ -217,7 +216,7 @@ describe("Moves - Roost", () => { await game.phaseInterceptor.to(TurnEndPhase); game.move.select(Moves.ROOST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to(MoveEffectPhase); // Should only be typeless type after roost and is grounded @@ -242,8 +241,8 @@ describe("Moves - Roost", () => { test( "Dual Type Pokemon afflicted with Forests Curse/Trick or Treat and post roost will become dual type and then become 3 type at end of turn", async () => { - game.override.enemyMoveset([Moves.TRICK_OR_TREAT, Moves.TRICK_OR_TREAT, Moves.TRICK_OR_TREAT, Moves.TRICK_OR_TREAT]); - await game.classicMode.startBattle([Species.MOLTRES]); + game.override.enemyMoveset([ Moves.TRICK_OR_TREAT, Moves.TRICK_OR_TREAT, Moves.TRICK_OR_TREAT, Moves.TRICK_OR_TREAT ]); + await game.classicMode.startBattle([ Species.MOLTRES ]); const playerPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.ROOST); await game.phaseInterceptor.to(MoveEffectPhase); diff --git a/src/test/moves/safeguard.test.ts b/src/test/moves/safeguard.test.ts index b21698d0298..6505162fd04 100644 --- a/src/test/moves/safeguard.test.ts +++ b/src/test/moves/safeguard.test.ts @@ -9,7 +9,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; - describe("Moves - Safeguard", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -29,12 +28,12 @@ describe("Moves - Safeguard", () => { game.override .battleType("single") .enemySpecies(Species.DRATINI) - .enemyMoveset([Moves.SAFEGUARD]) + .enemyMoveset([ Moves.SAFEGUARD ]) .enemyAbility(Abilities.BALL_FETCH) .enemyLevel(5) .starterSpecies(Species.DRATINI) - .moveset([Moves.NUZZLE, Moves.SPORE, Moves.YAWN, Moves.SPLASH]) - .ability(Abilities.BALL_FETCH); + .moveset([ Moves.NUZZLE, Moves.SPORE, Moves.YAWN, Moves.SPLASH ]) + .ability(Abilities.UNNERVE); // Stop wild Pokemon from potentially eating Lum Berry }); it("protects from damaging moves with additional effects", async () => { @@ -42,7 +41,7 @@ describe("Moves - Safeguard", () => { const enemy = game.scene.getEnemyPokemon()!; game.move.select(Moves.NUZZLE); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); expect(enemy.status).toBeUndefined(); @@ -53,19 +52,19 @@ describe("Moves - Safeguard", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.SPORE); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); expect(enemyPokemon.status).toBeUndefined(); }); it("protects from confusion", async () => { - game.override.moveset([Moves.CONFUSE_RAY]); + game.override.moveset([ Moves.CONFUSE_RAY ]); await game.classicMode.startBattle(); const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.CONFUSE_RAY); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); expect(enemyPokemon.summonData.tags).toEqual([]); @@ -79,7 +78,7 @@ describe("Moves - Safeguard", () => { game.move.select(Moves.SPORE, 0, BattlerIndex.ENEMY_2); game.move.select(Moves.NUZZLE, 1, BattlerIndex.ENEMY_2); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("BerryPhase"); @@ -94,7 +93,7 @@ describe("Moves - Safeguard", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.YAWN); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); expect(enemyPokemon.summonData.tags).toEqual([]); @@ -105,7 +104,7 @@ describe("Moves - Safeguard", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.YAWN); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.toNextTurn(); game.move.select(Moves.SPLASH); @@ -115,18 +114,18 @@ describe("Moves - Safeguard", () => { }); it("doesn't protect from self-inflicted via Rest or Flame Orb", async () => { - game.override.enemyHeldItems([{name: "FLAME_ORB"}]); + game.override.enemyHeldItems([{ name: "FLAME_ORB" }]); await game.classicMode.startBattle(); const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.SPLASH); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); enemyPokemon.damageAndUpdate(1); expect(enemyPokemon.status?.effect).toEqual(StatusEffect.BURN); - game.override.enemyMoveset([Moves.REST]); + game.override.enemyMoveset([ Moves.REST ]); // Force the moveset to update mid-battle // TODO: Remove after enemy AI rework is in enemyPokemon.getMoveset(); @@ -144,9 +143,9 @@ describe("Moves - Safeguard", () => { const enemyPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.SPLASH); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.toNextTurn(); - game.override.enemyMoveset([Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE ]); game.move.select(Moves.SPLASH); await game.toNextTurn(); diff --git a/src/test/moves/scale_shot.test.ts b/src/test/moves/scale_shot.test.ts index 412ce6687c6..e4d768fa13a 100644 --- a/src/test/moves/scale_shot.test.ts +++ b/src/test/moves/scale_shot.test.ts @@ -1,3 +1,5 @@ +import { BattlerIndex } from "#app/battle"; +import { allMoves } from "#app/data/move"; import { DamagePhase } from "#app/phases/damage-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MoveEndPhase } from "#app/phases/move-end-phase"; @@ -8,7 +10,7 @@ import { Species } from "#enums/species"; import { Stat } from "#enums/stat"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; describe("Moves - Scale Shot", () => { let phaserGame: Phaser.Game; @@ -27,48 +29,57 @@ describe("Moves - Scale Shot", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.SCALE_SHOT]) + .moveset([ Moves.SCALE_SHOT ]) .battleType("single") .disableCrits() - .starterSpecies(Species.MINCCINO) .ability(Abilities.NO_GUARD) .passiveAbility(Abilities.SKILL_LINK) - .enemyAbility(Abilities.SHEER_FORCE) - .enemyPassiveAbility(Abilities.STALL) - .enemyMoveset(Moves.SKILL_SWAP) - .enemyLevel(5); + .enemyMoveset(Moves.SPLASH) + .enemyLevel(3); }); it("applies stat changes after last hit", async () => { - await game.classicMode.startBattle([Species.FORRETRESS]); + game.override.enemySpecies(Species.FORRETRESS); + + await game.classicMode.startBattle([ Species.MINCCINO ]); const minccino = game.scene.getPlayerPokemon()!; game.move.select(Moves.SCALE_SHOT); + + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + await game.phaseInterceptor.to(MoveEffectPhase); await game.phaseInterceptor.to(DamagePhase); + + //check that stats haven't changed after one or two hits have occurred await game.phaseInterceptor.to(MoveEffectPhase); - expect (minccino?.getStatStage(Stat.DEF)).toBe(0); - expect (minccino?.getStatStage(Stat.SPD)).toBe(0); + expect(minccino.getStatStage(Stat.DEF)).toBe(0); + expect(minccino.getStatStage(Stat.SPD)).toBe(0); + + //check that stats changed on last hit await game.phaseInterceptor.to(MoveEndPhase); - expect (minccino.getStatStage(Stat.DEF)).toBe(-1); - expect (minccino.getStatStage(Stat.SPD)).toBe(1); + expect(minccino.getStatStage(Stat.DEF)).toBe(-1); + expect(minccino.getStatStage(Stat.SPD)).toBe(1); }); it("unaffected by sheer force", async () => { - await game.classicMode.startBattle([Species.WOBBUFFET]); + const moveToCheck = allMoves[Moves.SCALE_SHOT]; + const basePower = moveToCheck.power; + + game.override.enemySpecies(Species.WOBBUFFET); + + vi.spyOn(moveToCheck, "calculateBattlePower"); + + await game.classicMode.startBattle([ Species.MINCCINO ]); const minccino = game.scene.getPlayerPokemon()!; - const wobbuffet = game.scene.getEnemyPokemon()!; - wobbuffet.setStat(Stat.HP, 100, true); - wobbuffet.hp = 100; + game.move.select(Moves.SCALE_SHOT); await game.phaseInterceptor.to(TurnEndPhase); - const hpafter1 = wobbuffet.hp; + //effect not nullified by sheer force - expect (minccino.getStatStage(Stat.DEF)).toBe(-1); - expect (minccino.getStatStage(Stat.SPD)).toBe(1); - game.move.select(Moves.SCALE_SHOT); - await game.phaseInterceptor.to(MoveEndPhase); - const hpafter2 = wobbuffet.hp; - //check damage not boosted- make damage before sheer force a little lower than theoretical boosted sheer force damage - expect (100 - hpafter1).toBe(hpafter1 - hpafter2); + expect(minccino.getStatStage(Stat.DEF)).toBe(-1); + expect(minccino.getStatStage(Stat.SPD)).toBe(1); + + //power not boosted by sheer force + expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(basePower); }); }); diff --git a/src/test/moves/secret_power.test.ts b/src/test/moves/secret_power.test.ts new file mode 100644 index 00000000000..ff0b5ae8c24 --- /dev/null +++ b/src/test/moves/secret_power.test.ts @@ -0,0 +1,89 @@ +import { Abilities } from "#enums/abilities"; +import { Biome } from "#enums/biome"; +import { Moves } from "#enums/moves"; +import { Stat } from "#enums/stat"; +import { allMoves, SecretPowerAttr } from "#app/data/move"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { StatusEffect } from "#enums/status-effect"; +import { BattlerIndex } from "#app/battle"; +import { ArenaTagType } from "#enums/arena-tag-type"; +import { ArenaTagSide } from "#app/data/arena-tag"; + +describe("Moves - Secret Power", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([ Moves.SECRET_POWER ]) + .ability(Abilities.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyLevel(60) + .enemyAbility(Abilities.BALL_FETCH); + }); + + it("Secret Power checks for an active terrain first then looks at the biome for its secondary effect", async () => { + game.override + .startingBiome(Biome.VOLCANO) + .enemyMoveset([ Moves.SPLASH, Moves.MISTY_TERRAIN ]); + vi.spyOn(allMoves[Moves.SECRET_POWER], "chance", "get").mockReturnValue(100); + await game.classicMode.startBattle([ Species.FEEBAS ]); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + + // No Terrain + Biome.VOLCANO --> Burn + game.move.select(Moves.SECRET_POWER); + await game.forceEnemyMove(Moves.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyPokemon.status?.effect).toBe(StatusEffect.BURN); + + // Misty Terrain --> SpAtk -1 + game.move.select(Moves.SECRET_POWER); + await game.forceEnemyMove(Moves.MISTY_TERRAIN); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(-1); + }); + + it("the 'rainbow' effect of fire+water pledge does not double the chance of secret power's secondary effect", + async () => { + game.override + .moveset([ Moves.FIRE_PLEDGE, Moves.WATER_PLEDGE, Moves.SECRET_POWER, Moves.SPLASH ]) + .enemyMoveset([ Moves.SPLASH ]) + .battleType("double"); + await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); + + const secretPowerAttr = allMoves[Moves.SECRET_POWER].getAttrs(SecretPowerAttr)[0]; + vi.spyOn(secretPowerAttr, "getMoveChance"); + + game.move.select(Moves.WATER_PLEDGE, 0, BattlerIndex.ENEMY); + game.move.select(Moves.FIRE_PLEDGE, 1, BattlerIndex.ENEMY_2); + + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(game.scene.arena.getTagOnSide(ArenaTagType.WATER_FIRE_PLEDGE, ArenaTagSide.PLAYER)).toBeDefined(); + + game.move.select(Moves.SECRET_POWER, 0, BattlerIndex.ENEMY); + game.move.select(Moves.SPLASH, 1); + + await game.phaseInterceptor.to("BerryPhase", false); + + expect(secretPowerAttr.getMoveChance).toHaveLastReturnedWith(30); + } + ); +}); diff --git a/src/test/moves/shed_tail.test.ts b/src/test/moves/shed_tail.test.ts index a976a614792..c4df6c574cb 100644 --- a/src/test/moves/shed_tail.test.ts +++ b/src/test/moves/shed_tail.test.ts @@ -23,7 +23,7 @@ describe("Moves - Shed Tail", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.SHED_TAIL]) + .moveset([ Moves.SHED_TAIL ]) .battleType("single") .enemySpecies(Species.SNORLAX) .enemyAbility(Abilities.BALL_FETCH) @@ -31,7 +31,7 @@ describe("Moves - Shed Tail", () => { }); it("transfers a Substitute doll to the switched in Pokemon", async () => { - await game.classicMode.startBattle([Species.MAGIKARP, Species.FEEBAS]); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.FEEBAS ]); const magikarp = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/shell_side_arm.test.ts b/src/test/moves/shell_side_arm.test.ts index 643313f1eae..9646d27f17e 100644 --- a/src/test/moves/shell_side_arm.test.ts +++ b/src/test/moves/shell_side_arm.test.ts @@ -26,7 +26,7 @@ describe("Moves - Shell Side Arm", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.SHELL_SIDE_ARM]) + .moveset([ Moves.SHELL_SIDE_ARM ]) .battleType("single") .startingLevel(100) .enemyLevel(100) @@ -37,7 +37,7 @@ describe("Moves - Shell Side Arm", () => { it("becomes a physical attack if forecasted to deal more damage as physical", async () => { game.override.enemySpecies(Species.SNORLAX); - await game.classicMode.startBattle([Species.RAMPARDOS]); + await game.classicMode.startBattle([ Species.RAMPARDOS ]); vi.spyOn(shellSideArmAttr, "apply"); @@ -50,7 +50,7 @@ describe("Moves - Shell Side Arm", () => { it("remains a special attack if forecasted to deal more damage as special", async () => { game.override.enemySpecies(Species.SLOWBRO); - await game.classicMode.startBattle([Species.XURKITREE]); + await game.classicMode.startBattle([ Species.XURKITREE ]); vi.spyOn(shellSideArmAttr, "apply"); @@ -65,12 +65,12 @@ describe("Moves - Shell Side Arm", () => { .enemySpecies(Species.SNORLAX) .enemyMoveset(Moves.COTTON_GUARD); - await game.classicMode.startBattle([Species.MANAPHY]); + await game.classicMode.startBattle([ Species.MANAPHY ]); vi.spyOn(shellSideArmAttr, "apply"); game.move.select(Moves.SHELL_SIDE_ARM); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase", false); expect(shellSideArmAttr.apply).toHaveLastReturnedWith(false); diff --git a/src/test/moves/shell_trap.test.ts b/src/test/moves/shell_trap.test.ts index 1dae00e24a5..04d3cf998b1 100644 --- a/src/test/moves/shell_trap.test.ts +++ b/src/test/moves/shell_trap.test.ts @@ -11,7 +11,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; - describe("Moves - Shell Trap", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -30,9 +29,9 @@ describe("Moves - Shell Trap", () => { game = new GameManager(phaserGame); game.override .battleType("double") - .moveset([Moves.SHELL_TRAP, Moves.SPLASH, Moves.BULLDOZE]) + .moveset([ Moves.SHELL_TRAP, Moves.SPLASH, Moves.BULLDOZE ]) .enemySpecies(Species.SNORLAX) - .enemyMoveset([Moves.RAZOR_LEAF]) + .enemyMoveset([ Moves.RAZOR_LEAF ]) .startingLevel(100) .enemyLevel(100); @@ -42,7 +41,7 @@ describe("Moves - Shell Trap", () => { it( "should activate after the user is hit by a physical attack", async () => { - await game.startBattle([Species.CHARIZARD, Species.TURTONATOR]); + await game.startBattle([ Species.CHARIZARD, Species.TURTONATOR ]); const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); @@ -50,7 +49,7 @@ describe("Moves - Shell Trap", () => { game.move.select(Moves.SPLASH); game.move.select(Moves.SHELL_TRAP, 1); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2 ]); await game.phaseInterceptor.to(MoveEndPhase); @@ -66,9 +65,9 @@ describe("Moves - Shell Trap", () => { it( "should fail if the user is only hit by special attacks", async () => { - game.override.enemyMoveset([Moves.SWIFT]); + game.override.enemyMoveset([ Moves.SWIFT ]); - await game.startBattle([Species.CHARIZARD, Species.TURTONATOR]); + await game.startBattle([ Species.CHARIZARD, Species.TURTONATOR ]); const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); @@ -76,7 +75,7 @@ describe("Moves - Shell Trap", () => { game.move.select(Moves.SPLASH); game.move.select(Moves.SHELL_TRAP, 1); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2 ]); await game.phaseInterceptor.to(MoveEndPhase); @@ -94,7 +93,7 @@ describe("Moves - Shell Trap", () => { async () => { game.override.enemyMoveset(Moves.SPLASH); - await game.startBattle([Species.CHARIZARD, Species.TURTONATOR]); + await game.startBattle([ Species.CHARIZARD, Species.TURTONATOR ]); const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); @@ -102,7 +101,7 @@ describe("Moves - Shell Trap", () => { game.move.select(Moves.SPLASH); game.move.select(Moves.SHELL_TRAP, 1); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER, BattlerIndex.PLAYER_2 ]); await game.phaseInterceptor.to(MoveEndPhase); @@ -120,7 +119,7 @@ describe("Moves - Shell Trap", () => { async () => { game.override.enemyMoveset(Moves.SPLASH); - await game.startBattle([Species.BLASTOISE, Species.CHARIZARD]); + await game.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); @@ -147,7 +146,7 @@ describe("Moves - Shell Trap", () => { game.override.battleType("single"); vi.spyOn(allMoves[Moves.RAZOR_LEAF], "priority", "get").mockReturnValue(-4); - await game.startBattle([Species.CHARIZARD]); + await game.startBattle([ Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/sketch.test.ts b/src/test/moves/sketch.test.ts new file mode 100644 index 00000000000..2e3eb97a76c --- /dev/null +++ b/src/test/moves/sketch.test.ts @@ -0,0 +1,53 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { MoveResult } from "#app/field/pokemon"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Moves - Sketch", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .ability(Abilities.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.SHUCKLE) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("Sketch should not fail even if a previous Sketch failed to retrieve a valid move and ran out of PP", async () => { + game.override.moveset([ Moves.SKETCH, Moves.SKETCH ]); + + await game.classicMode.startBattle([ Species.REGIELEKI ]); + const playerPokemon = game.scene.getPlayerPokemon(); + + game.move.select(Moves.SKETCH); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(playerPokemon?.getLastXMoves()[0].result).toBe(MoveResult.FAIL); + const moveSlot0 = playerPokemon?.getMoveset()[0]; + expect(moveSlot0?.moveId).toBe(Moves.SKETCH); + expect(moveSlot0?.getPpRatio()).toBe(0); + + await game.toNextTurn(); + game.move.select(Moves.SKETCH); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(playerPokemon?.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS); + // Can't verify if the player Pokemon's moveset was successfully changed because of overrides. + }); +}); diff --git a/src/test/moves/sparkly_swirl.test.ts b/src/test/moves/sparkly_swirl.test.ts index 83c154e57e7..8449f2785f8 100644 --- a/src/test/moves/sparkly_swirl.test.ts +++ b/src/test/moves/sparkly_swirl.test.ts @@ -27,7 +27,7 @@ describe("Moves - Sparkly Swirl", () => { .enemyLevel(100) .enemyMoveset(Moves.SPLASH) .enemyAbility(Abilities.BALL_FETCH) - .moveset([Moves.SPARKLY_SWIRL, Moves.SPLASH]) + .moveset([ Moves.SPARKLY_SWIRL, Moves.SPLASH ]) .ability(Abilities.BALL_FETCH); vi.spyOn(allMoves[Moves.SPARKLY_SWIRL], "accuracy", "get").mockReturnValue(100); @@ -37,8 +37,8 @@ describe("Moves - Sparkly Swirl", () => { game.override .battleType("double") .statusEffect(StatusEffect.BURN); - await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA, Species.RATTATA]); - const [leftPlayer, rightPlayer, partyPokemon] = game.scene.getParty(); + await game.classicMode.startBattle([ Species.RATTATA, Species.RATTATA, Species.RATTATA ]); + const [ leftPlayer, rightPlayer, partyPokemon ] = game.scene.getParty(); const leftOpp = game.scene.getEnemyPokemon()!; vi.spyOn(leftPlayer, "resetStatus"); @@ -63,8 +63,8 @@ describe("Moves - Sparkly Swirl", () => { game.override .battleType("double") .enemyStatusEffect(StatusEffect.BURN); - await game.classicMode.startBattle([Species.RATTATA, Species.RATTATA]); - const [leftOpp, rightOpp] = game.scene.getEnemyField(); + await game.classicMode.startBattle([ Species.RATTATA, Species.RATTATA ]); + const [ leftOpp, rightOpp ] = game.scene.getEnemyField(); vi.spyOn(leftOpp, "resetStatus"); vi.spyOn(rightOpp, "resetStatus"); diff --git a/src/test/moves/spikes.test.ts b/src/test/moves/spikes.test.ts index aa59912d802..1dd13f8f65e 100644 --- a/src/test/moves/spikes.test.ts +++ b/src/test/moves/spikes.test.ts @@ -28,11 +28,11 @@ describe("Moves - Spikes", () => { .enemyAbility(Abilities.BALL_FETCH) .ability(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH) - .moveset([Moves.SPIKES, Moves.SPLASH, Moves.ROAR]); + .moveset([ Moves.SPIKES, Moves.SPLASH, Moves.ROAR ]); }); it("should not damage the team that set them", async () => { - await game.startBattle([Species.MIGHTYENA, Species.POOCHYENA]); + await game.startBattle([ Species.MIGHTYENA, Species.POOCHYENA ]); game.move.select(Moves.SPIKES); await game.toNextTurn(); @@ -52,7 +52,7 @@ describe("Moves - Spikes", () => { it("should damage opposing pokemon that are forced to switch in", async () => { game.override.startingWave(5); - await game.startBattle([Species.MIGHTYENA, Species.POOCHYENA]); + await game.startBattle([ Species.MIGHTYENA, Species.POOCHYENA ]); game.move.select(Moves.SPIKES); await game.toNextTurn(); @@ -66,7 +66,7 @@ describe("Moves - Spikes", () => { it("should damage opposing pokemon that choose to switch in", async () => { game.override.startingWave(5); - await game.startBattle([Species.MIGHTYENA, Species.POOCHYENA]); + await game.startBattle([ Species.MIGHTYENA, Species.POOCHYENA ]); game.move.select(Moves.SPIKES); await game.toNextTurn(); diff --git a/src/test/moves/spit_up.test.ts b/src/test/moves/spit_up.test.ts index 412360c2664..8e418858e8d 100644 --- a/src/test/moves/spit_up.test.ts +++ b/src/test/moves/spit_up.test.ts @@ -47,7 +47,7 @@ describe("Moves - Spit Up", () => { const stacksToSetup = 1; const expectedPower = 100; - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; pokemon.addTag(BattlerTagType.STOCKPILING); @@ -69,7 +69,7 @@ describe("Moves - Spit Up", () => { const stacksToSetup = 2; const expectedPower = 200; - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; pokemon.addTag(BattlerTagType.STOCKPILING); @@ -92,7 +92,7 @@ describe("Moves - Spit Up", () => { const stacksToSetup = 3; const expectedPower = 300; - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; pokemon.addTag(BattlerTagType.STOCKPILING); @@ -114,7 +114,7 @@ describe("Moves - Spit Up", () => { }); it("fails without stacks", async () => { - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; @@ -131,7 +131,7 @@ describe("Moves - Spit Up", () => { describe("restores stat boosts granted by stacks", () => { it("decreases stats based on stored values (both boosts equal)", async () => { - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; pokemon.addTag(BattlerTagType.STOCKPILING); @@ -158,7 +158,7 @@ describe("Moves - Spit Up", () => { }); it("decreases stats based on stored values (different boosts)", async () => { - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; pokemon.addTag(BattlerTagType.STOCKPILING); diff --git a/src/test/moves/spotlight.test.ts b/src/test/moves/spotlight.test.ts index 6324c3dc6ec..095f7d80bfe 100644 --- a/src/test/moves/spotlight.test.ts +++ b/src/test/moves/spotlight.test.ts @@ -7,7 +7,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; - describe("Moves - Spotlight", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -29,14 +28,14 @@ describe("Moves - Spotlight", () => { game.override.enemySpecies(Species.SNORLAX); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK]); - game.override.enemyMoveset([Moves.FOLLOW_ME, Moves.SPLASH]); + game.override.moveset([ Moves.FOLLOW_ME, Moves.RAGE_POWDER, Moves.SPOTLIGHT, Moves.QUICK_ATTACK ]); + game.override.enemyMoveset([ Moves.FOLLOW_ME, Moves.SPLASH ]); }); test( "move should redirect attacks to the target", async () => { - await game.classicMode.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); const enemyPokemon = game.scene.getEnemyField(); @@ -56,7 +55,7 @@ describe("Moves - Spotlight", () => { test( "move should cause other redirection moves to fail", async () => { - await game.classicMode.startBattle([Species.AMOONGUSS, Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.AMOONGUSS, Species.CHARIZARD ]); const enemyPokemon = game.scene.getEnemyField(); diff --git a/src/test/moves/steamroller.test.ts b/src/test/moves/steamroller.test.ts index cbbb3a22593..9d16643ec5d 100644 --- a/src/test/moves/steamroller.test.ts +++ b/src/test/moves/steamroller.test.ts @@ -25,12 +25,12 @@ describe("Moves - Steamroller", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override.moveset([Moves.STEAMROLLER]).battleType("single").enemyAbility(Abilities.BALL_FETCH); + game.override.moveset([ Moves.STEAMROLLER ]).battleType("single").enemyAbility(Abilities.BALL_FETCH); }); it("should always hit a minimzed target with double damage", async () => { game.override.enemySpecies(Species.DITTO).enemyMoveset(Moves.MINIMIZE); - await game.classicMode.startBattle([Species.IRON_BOULDER]); + await game.classicMode.startBattle([ Species.IRON_BOULDER ]); const ditto = game.scene.getEnemyPokemon()!; vi.spyOn(ditto, "getAttackDamage"); @@ -41,13 +41,13 @@ describe("Moves - Steamroller", () => { vi.spyOn(ironBoulder, "getAccuracyMultiplier"); // Turn 1 game.move.select(Moves.STEAMROLLER); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.toNextTurn(); // Turn 2 game.move.select(Moves.STEAMROLLER); await game.toNextTurn(); - const [dmgCalcTurn1, dmgCalcTurn2]: DamageCalculationResult[] = vi + const [ dmgCalcTurn1, dmgCalcTurn2 ]: DamageCalculationResult[] = vi .mocked(ditto.getAttackDamage) .mock.results.map((r) => r.value); diff --git a/src/test/moves/stockpile.test.ts b/src/test/moves/stockpile.test.ts index 141ce79eb33..d3239856ed7 100644 --- a/src/test/moves/stockpile.test.ts +++ b/src/test/moves/stockpile.test.ts @@ -33,12 +33,12 @@ describe("Moves - Stockpile", () => { game.override.enemyAbility(Abilities.NONE); game.override.startingLevel(2000); - game.override.moveset([Moves.STOCKPILE, Moves.SPLASH]); + game.override.moveset([ Moves.STOCKPILE, Moves.SPLASH ]); game.override.ability(Abilities.NONE); }); it("gains a stockpile stack and raises user's DEF and SPDEF stat stages by 1 on each use, fails at max stacks (3)", async () => { - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const user = game.scene.getPlayerPokemon()!; @@ -77,7 +77,7 @@ describe("Moves - Stockpile", () => { }); it("gains a stockpile stack even if user's DEF and SPDEF stat stages are at +6", async () => { - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const user = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/substitute.test.ts b/src/test/moves/substitute.test.ts index 3099446f081..92f66c967c4 100644 --- a/src/test/moves/substitute.test.ts +++ b/src/test/moves/substitute.test.ts @@ -38,7 +38,7 @@ describe("Moves - Substitute", () => { game.override .battleType("single") - .moveset([Moves.SUBSTITUTE, Moves.SWORDS_DANCE, Moves.TACKLE, Moves.SPLASH]) + .moveset([ Moves.SUBSTITUTE, Moves.SWORDS_DANCE, Moves.TACKLE, Moves.SPLASH ]) .enemySpecies(Species.SNORLAX) .enemyAbility(Abilities.INSOMNIA) .enemyMoveset(Moves.SPLASH) @@ -49,7 +49,7 @@ describe("Moves - Substitute", () => { it( "should cause the user to take damage", async () => { - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -57,7 +57,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("MoveEndPhase", false); - expect(leadPokemon.hp).toBe(Math.ceil(leadPokemon.getMaxHp() * 3/4)); + expect(leadPokemon.hp).toBe(Math.ceil(leadPokemon.getMaxHp() * 3 / 4)); } ); @@ -66,7 +66,7 @@ describe("Moves - Substitute", () => { async () => { game.override.enemyMoveset(Moves.TACKLE); - await game.classicMode.startBattle([Species.SKARMORY]); + await game.classicMode.startBattle([ Species.SKARMORY ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -74,7 +74,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("MoveEndPhase", false); - expect(leadPokemon.hp).toBe(Math.ceil(leadPokemon.getMaxHp() * 3/4)); + expect(leadPokemon.hp).toBe(Math.ceil(leadPokemon.getMaxHp() * 3 / 4)); expect(leadPokemon.getTag(BattlerTagType.SUBSTITUTE)).toBeDefined(); const postSubHp = leadPokemon.hp; @@ -92,7 +92,7 @@ describe("Moves - Substitute", () => { game.override.enemyMoveset(Moves.GIGA_IMPACT); vi.spyOn(allMoves[Moves.GIGA_IMPACT], "accuracy", "get").mockReturnValue(100); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -100,7 +100,7 @@ describe("Moves - Substitute", () => { await game.phaseInterceptor.to("MoveEndPhase", false); - expect(leadPokemon.hp).toBe(Math.ceil(leadPokemon.getMaxHp() * 3/4)); + expect(leadPokemon.hp).toBe(Math.ceil(leadPokemon.getMaxHp() * 3 / 4)); expect(leadPokemon.getTag(BattlerTagType.SUBSTITUTE)).toBeDefined(); const postSubHp = leadPokemon.hp; @@ -116,7 +116,7 @@ describe("Moves - Substitute", () => { async () => { game.override.enemyMoveset(Moves.CHARM); - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -134,7 +134,7 @@ describe("Moves - Substitute", () => { async () => { game.override.enemyMoveset(Moves.ECHOED_VOICE); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -158,7 +158,7 @@ describe("Moves - Substitute", () => { game.override.enemyMoveset(Moves.TACKLE); game.override.enemyAbility(Abilities.INFILTRATOR); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -179,7 +179,7 @@ describe("Moves - Substitute", () => { it( "shouldn't block the user's own status moves", async () => { - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -201,7 +201,7 @@ describe("Moves - Substitute", () => { async () => { game.override.moveset(Moves.LIGHT_SCREEN); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; vi.spyOn(leadPokemon, "getMoveEffectiveness"); @@ -222,7 +222,7 @@ describe("Moves - Substitute", () => { async () => { game.override.enemyMoveset(Moves.STEALTH_ROCK); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; vi.spyOn(leadPokemon, "getMoveEffectiveness"); @@ -243,7 +243,7 @@ describe("Moves - Substitute", () => { .moveset(Moves.TRICK_ROOM) .enemyMoveset(Moves.GRAVITY); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const pokemon = game.scene.getField(true); pokemon.forEach(p => { @@ -267,7 +267,7 @@ describe("Moves - Substitute", () => { game.override.enemyMoveset(Moves.FAKE_OUT); game.override.startingLevel(1); // Ensures the Substitute will break - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -288,7 +288,7 @@ describe("Moves - Substitute", () => { vi.spyOn(allMoves[Moves.SAND_TOMB], "accuracy", "get").mockReturnValue(100); game.override.enemyMoveset(Moves.SAND_TOMB); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -308,7 +308,7 @@ describe("Moves - Substitute", () => { vi.spyOn(allMoves[Moves.LIQUIDATION], "chance", "get").mockReturnValue(100); game.override.enemyMoveset(Moves.LIQUIDATION); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -327,7 +327,7 @@ describe("Moves - Substitute", () => { async () => { game.override.enemyMoveset(Moves.NUZZLE); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -345,10 +345,10 @@ describe("Moves - Substitute", () => { "should prevent the user's items from being stolen", async () => { game.override.enemyMoveset(Moves.THIEF); - vi.spyOn(allMoves[Moves.THIEF], "attrs", "get").mockReturnValue([new StealHeldItemChanceAttr(1.0)]); // give Thief 100% steal rate - game.override.startingHeldItems([{name: "BERRY", type: BerryType.SITRUS}]); + vi.spyOn(allMoves[Moves.THIEF], "attrs", "get").mockReturnValue([ new StealHeldItemChanceAttr(1.0) ]); // give Thief 100% steal rate + game.override.startingHeldItems([{ name: "BERRY", type: BerryType.SITRUS }]); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -365,10 +365,10 @@ describe("Moves - Substitute", () => { it( "should prevent the user's items from being removed", async () => { - game.override.moveset([Moves.KNOCK_OFF]); - game.override.enemyHeldItems([{name: "BERRY", type: BerryType.SITRUS}]); + game.override.moveset([ Moves.KNOCK_OFF ]); + game.override.enemyHeldItems([{ name: "BERRY", type: BerryType.SITRUS }]); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -387,9 +387,9 @@ describe("Moves - Substitute", () => { "move effect should prevent the user's berries from being stolen and eaten", async () => { game.override.enemyMoveset(Moves.BUG_BITE); - game.override.startingHeldItems([{name: "BERRY", type: BerryType.SITRUS}]); + game.override.startingHeldItems([{ name: "BERRY", type: BerryType.SITRUS }]); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -413,7 +413,7 @@ describe("Moves - Substitute", () => { async () => { game.override.enemyMoveset(Moves.CLEAR_SMOG); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -433,7 +433,7 @@ describe("Moves - Substitute", () => { game.override.enemyMoveset(Moves.MAGICAL_TORQUE); vi.spyOn(allMoves[Moves.MAGICAL_TORQUE], "chance", "get").mockReturnValue(100); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -451,9 +451,9 @@ describe("Moves - Substitute", () => { it( "should transfer to the switched in Pokemon when the source uses Baton Pass", async () => { - game.override.moveset([Moves.SUBSTITUTE, Moves.BATON_PASS]); + game.override.moveset([ Moves.SUBSTITUTE, Moves.BATON_PASS ]); - await game.classicMode.startBattle([Species.BLASTOISE, Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.BLASTOISE, Species.CHARIZARD ]); const leadPokemon = game.scene.getPlayerPokemon()!; @@ -469,7 +469,7 @@ describe("Moves - Substitute", () => { const switchedPokemon = game.scene.getPlayerPokemon()!; const subTag = switchedPokemon.getTag(SubstituteTag)!; expect(subTag).toBeDefined(); - expect(subTag.hp).toBe(Math.floor(leadPokemon.getMaxHp() * 1/4)); + expect(subTag.hp).toBe(Math.floor(leadPokemon.getMaxHp() * 1 / 4)); } ); @@ -479,7 +479,7 @@ describe("Moves - Substitute", () => { game.override.enemyMoveset(Moves.TACKLE); game.override.ability(Abilities.ROUGH_SKIN); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -495,12 +495,12 @@ describe("Moves - Substitute", () => { "should prevent the source's Focus Punch from failing when hit", async () => { game.override.enemyMoveset(Moves.TACKLE); - game.override.moveset([Moves.FOCUS_PUNCH]); + game.override.moveset([ Moves.FOCUS_PUNCH ]); // Make Focus Punch 40 power to avoid a KO vi.spyOn(allMoves[Moves.FOCUS_PUNCH], "calculateBattlePower").mockReturnValue(40); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -520,9 +520,9 @@ describe("Moves - Substitute", () => { "should not allow Shell Trap to activate when attacked", async () => { game.override.enemyMoveset(Moves.TACKLE); - game.override.moveset([Moves.SHELL_TRAP]); + game.override.moveset([ Moves.SHELL_TRAP ]); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerPokemon()!; @@ -540,9 +540,9 @@ describe("Moves - Substitute", () => { "should not allow Beak Blast to burn opponents when hit", async () => { game.override.enemyMoveset(Moves.TACKLE); - game.override.moveset([Moves.BEAK_BLAST]); + game.override.moveset([ Moves.BEAK_BLAST ]); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -561,9 +561,9 @@ describe("Moves - Substitute", () => { "should cause incoming attacks to not activate Counter", async () => { game.override.enemyMoveset(Moves.TACKLE); - game.override.moveset([Moves.COUNTER]); + game.override.moveset([ Moves.COUNTER ]); - await game.classicMode.startBattle([Species.BLASTOISE]); + await game.classicMode.startBattle([ Species.BLASTOISE ]); const playerPokemon = game.scene.getPlayerPokemon()!; const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -584,7 +584,7 @@ describe("Moves - Substitute", () => { async () => { game.override.enemyMoveset(Moves.SAPPY_SEED); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); const playerPokemon = game.scene.getPlayerPokemon()!; @@ -592,7 +592,7 @@ describe("Moves - Substitute", () => { game.move.select(Moves.SPLASH); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); // enemy uses Sappy Seed first + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); // enemy uses Sappy Seed first await game.move.forceHit(); // forces Sappy Seed to hit await game.phaseInterceptor.to("MoveEndPhase"); diff --git a/src/test/moves/swallow.test.ts b/src/test/moves/swallow.test.ts index b8ca941d0ee..2aee4d2604a 100644 --- a/src/test/moves/swallow.test.ts +++ b/src/test/moves/swallow.test.ts @@ -33,7 +33,7 @@ describe("Moves - Swallow", () => { game.override.enemyAbility(Abilities.NONE); game.override.enemyLevel(2000); - game.override.moveset([Moves.SWALLOW, Moves.SWALLOW, Moves.SWALLOW, Moves.SWALLOW]); + game.override.moveset([ Moves.SWALLOW, Moves.SWALLOW, Moves.SWALLOW, Moves.SWALLOW ]); game.override.ability(Abilities.NONE); }); @@ -42,7 +42,7 @@ describe("Moves - Swallow", () => { const stacksToSetup = 1; const expectedHeal = 25; - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; vi.spyOn(pokemon, "getMaxHp").mockReturnValue(100); @@ -69,7 +69,7 @@ describe("Moves - Swallow", () => { const stacksToSetup = 2; const expectedHeal = 50; - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; vi.spyOn(pokemon, "getMaxHp").mockReturnValue(100); @@ -97,7 +97,7 @@ describe("Moves - Swallow", () => { const stacksToSetup = 3; const expectedHeal = 100; - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; vi.spyOn(pokemon, "getMaxHp").mockReturnValue(100); @@ -124,7 +124,7 @@ describe("Moves - Swallow", () => { }); it("fails without stacks", async () => { - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; @@ -139,7 +139,7 @@ describe("Moves - Swallow", () => { describe("restores stat stage boosts granted by stacks", () => { it("decreases stats based on stored values (both boosts equal)", async () => { - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; pokemon.addTag(BattlerTagType.STOCKPILING); @@ -164,7 +164,7 @@ describe("Moves - Swallow", () => { }); it("lower stat stages based on stored values (different boosts)", async () => { - await game.startBattle([Species.ABOMASNOW]); + await game.startBattle([ Species.ABOMASNOW ]); const pokemon = game.scene.getPlayerPokemon()!; pokemon.addTag(BattlerTagType.STOCKPILING); diff --git a/src/test/moves/syrup_bomb.test.ts b/src/test/moves/syrup_bomb.test.ts index 20cd590e457..ea2f8b6bab3 100644 --- a/src/test/moves/syrup_bomb.test.ts +++ b/src/test/moves/syrup_bomb.test.ts @@ -1,4 +1,3 @@ -import { allMoves } from "#app/data/move"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import { Abilities } from "#enums/abilities"; @@ -7,7 +6,7 @@ import { Stat } from "#enums/stat"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { BattlerIndex } from "#app/battle"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Moves - SYRUP BOMB", () => { let phaserGame: Phaser.Game; @@ -26,26 +25,27 @@ describe("Moves - SYRUP BOMB", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .starterSpecies(Species.MAGIKARP) + .battleType("single") .enemySpecies(Species.SNORLAX) + .enemyAbility(Abilities.BALL_FETCH) + .ability(Abilities.BALL_FETCH) .startingLevel(30) .enemyLevel(100) - .moveset([Moves.SYRUP_BOMB, Moves.SPLASH]) + .moveset([ Moves.SYRUP_BOMB, Moves.SPLASH ]) .enemyMoveset(Moves.SPLASH); - vi.spyOn(allMoves[Moves.SYRUP_BOMB], "accuracy", "get").mockReturnValue(100); }); //Bulbapedia Reference: https://bulbapedia.bulbagarden.net/wiki/syrup_bomb_(move) it("decreases the target Pokemon's speed stat once per turn for 3 turns", async () => { - await game.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const targetPokemon = game.scene.getEnemyPokemon()!; expect(targetPokemon.getStatStage(Stat.SPD)).toBe(0); game.move.select(Moves.SYRUP_BOMB); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.move.forceHit(); await game.toNextTurn(); expect(targetPokemon.getTag(BattlerTagType.SYRUP_BOMB)).toBeDefined(); @@ -66,12 +66,12 @@ describe("Moves - SYRUP BOMB", () => { it("does not affect Pokemon with the ability Bulletproof", async () => { game.override.enemyAbility(Abilities.BULLETPROOF); - await game.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const targetPokemon = game.scene.getEnemyPokemon()!; game.move.select(Moves.SYRUP_BOMB); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.move.forceHit(); await game.toNextTurn(); expect(targetPokemon.isFullHp()).toBe(true); @@ -79,4 +79,18 @@ describe("Moves - SYRUP BOMB", () => { expect(targetPokemon.getStatStage(Stat.SPD)).toBe(0); } ); + + it("stops lowering the target's speed if the user leaves the field", async () => { + await game.classicMode.startBattle([ Species.FEEBAS, Species.MILOTIC ]); + + game.move.select(Moves.SYRUP_BOMB); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + await game.move.forceHit(); + await game.toNextTurn(); + + game.doSwitchPokemon(1); + await game.toNextTurn(); + + expect(game.scene.getEnemyPokemon()!.getStatStage(Stat.SPD)).toBe(-1); + }); }); diff --git a/src/test/moves/tackle.test.ts b/src/test/moves/tackle.test.ts index b25c7524a1a..5d5ff1a366d 100644 --- a/src/test/moves/tackle.test.ts +++ b/src/test/moves/tackle.test.ts @@ -29,8 +29,8 @@ describe("Moves - Tackle", () => { game.override.enemySpecies(Species.MAGIKARP); game.override.startingLevel(1); game.override.startingWave(97); - game.override.moveset([moveToUse]); - game.override.enemyMoveset([Moves.GROWTH, Moves.GROWTH, Moves.GROWTH, Moves.GROWTH]); + game.override.moveset([ moveToUse ]); + game.override.enemyMoveset([ Moves.GROWTH, Moves.GROWTH, Moves.GROWTH, Moves.GROWTH ]); game.override.disableCrits(); }); diff --git a/src/test/moves/tailwind.test.ts b/src/test/moves/tailwind.test.ts index 6a08cfe802f..a26dde82824 100644 --- a/src/test/moves/tailwind.test.ts +++ b/src/test/moves/tailwind.test.ts @@ -25,12 +25,12 @@ describe("Moves - Tailwind", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override.battleType("double"); - game.override.moveset([Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM]); + game.override.moveset([ Moves.TAILWIND, Moves.SPLASH, Moves.PETAL_BLIZZARD, Moves.SANDSTORM ]); game.override.enemyMoveset(Moves.SPLASH); }); it("doubles the Speed stat of the Pokemons on its side", async () => { - await game.startBattle([Species.MAGIKARP, Species.MEOWTH]); + await game.startBattle([ Species.MAGIKARP, Species.MEOWTH ]); const magikarp = game.scene.getPlayerField()[0]; const meowth = game.scene.getPlayerField()[1]; @@ -53,7 +53,7 @@ describe("Moves - Tailwind", () => { it("lasts for 4 turns", async () => { game.override.battleType("single"); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); game.move.select(Moves.TAILWIND); await game.toNextTurn(); @@ -76,7 +76,7 @@ describe("Moves - Tailwind", () => { it("does not affect the opposing side", async () => { game.override.battleType("single"); - await game.startBattle([Species.MAGIKARP]); + await game.startBattle([ Species.MAGIKARP ]); const ally = game.scene.getPlayerPokemon()!; const enemy = game.scene.getEnemyPokemon()!; diff --git a/src/test/moves/tar_shot.test.ts b/src/test/moves/tar_shot.test.ts index 2385bd18265..4734da366e4 100644 --- a/src/test/moves/tar_shot.test.ts +++ b/src/test/moves/tar_shot.test.ts @@ -29,12 +29,12 @@ describe("Moves - Tar Shot", () => { .enemyMoveset(Moves.SPLASH) .enemySpecies(Species.TANGELA) .enemyLevel(1000) - .moveset([Moves.TAR_SHOT, Moves.FIRE_PUNCH]) + .moveset([ Moves.TAR_SHOT, Moves.FIRE_PUNCH ]) .disableCrits(); }); it("lowers the target's Speed stat by one stage and doubles the effectiveness of Fire-type moves used on the target", async () => { - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const enemy = game.scene.getEnemyPokemon()!; @@ -48,14 +48,14 @@ describe("Moves - Tar Shot", () => { await game.toNextTurn(); game.move.select(Moves.FIRE_PUNCH); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(4); }); it("will not double the effectiveness of Fire-type moves used on a target that is already under the effect of Tar Shot (but may still lower its Speed)", async () => { - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const enemy = game.scene.getEnemyPokemon()!; @@ -76,7 +76,7 @@ describe("Moves - Tar Shot", () => { await game.toNextTurn(); game.move.select(Moves.FIRE_PUNCH); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(4); @@ -84,7 +84,7 @@ describe("Moves - Tar Shot", () => { it("does not double the effectiveness of Fire-type moves against a Pokémon that is Terastallized", async () => { game.override.enemyHeldItems([{ name: "TERA_SHARD", type: Type.GRASS }]).enemySpecies(Species.SPRIGATITO); - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const enemy = game.scene.getEnemyPokemon()!; @@ -98,7 +98,7 @@ describe("Moves - Tar Shot", () => { await game.toNextTurn(); game.move.select(Moves.FIRE_PUNCH); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(2); @@ -106,7 +106,7 @@ describe("Moves - Tar Shot", () => { it("doubles the effectiveness of Fire-type moves against a Pokémon that is already under the effects of Tar Shot before it Terastallized", async () => { game.override.enemySpecies(Species.SPRIGATITO); - await game.classicMode.startBattle([Species.PIKACHU]); + await game.classicMode.startBattle([ Species.PIKACHU ]); const enemy = game.scene.getEnemyPokemon()!; @@ -122,7 +122,7 @@ describe("Moves - Tar Shot", () => { game.override.enemyHeldItems([{ name: "TERA_SHARD", type: Type.GRASS }]); game.move.select(Moves.FIRE_PUNCH); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.getMoveEffectiveness).toHaveReturnedWith(4); diff --git a/src/test/moves/taunt.test.ts b/src/test/moves/taunt.test.ts index 50bb2fee9df..a425a048a2c 100644 --- a/src/test/moves/taunt.test.ts +++ b/src/test/moves/taunt.test.ts @@ -25,13 +25,13 @@ describe("Moves - Taunt", () => { game.override .battleType("single") .enemyAbility(Abilities.BALL_FETCH) - .enemyMoveset([Moves.TAUNT, Moves.SPLASH]) + .enemyMoveset([ Moves.TAUNT, Moves.SPLASH ]) .enemySpecies(Species.SHUCKLE) - .moveset([Moves.GROWL]); + .moveset([ Moves.GROWL ]); }); it("Pokemon should not be able to use Status Moves", async () => { - await game.classicMode.startBattle([Species.REGIELEKI]); + await game.classicMode.startBattle([ Species.REGIELEKI ]); const playerPokemon = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/telekinesis.test.ts b/src/test/moves/telekinesis.test.ts new file mode 100644 index 00000000000..76c0d001f00 --- /dev/null +++ b/src/test/moves/telekinesis.test.ts @@ -0,0 +1,124 @@ +import { BattlerTagType } from "#enums/battler-tag-type"; +import { allMoves } from "#app/data/move"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { MoveResult } from "#app/field/pokemon"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; + +describe("Moves - Telekinesis", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([ Moves.TELEKINESIS, Moves.TACKLE, Moves.MUD_SHOT, Moves.SMACK_DOWN ]) + .battleType("single") + .enemySpecies(Species.SNORLAX) + .enemyLevel(60) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset([ Moves.SPLASH ]); + }); + + it("Telekinesis makes the affected vulnerable to most attacking moves regardless of accuracy", async () => { + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + const enemyOpponent = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.TELEKINESIS); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined(); + expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeDefined(); + + await game.toNextTurn(); + vi.spyOn(allMoves[Moves.TACKLE], "accuracy", "get").mockReturnValue(0); + game.move.select(Moves.TACKLE); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyOpponent.isFullHp()).toBe(false); + }); + + it("Telekinesis makes the affected airborne and immune to most Ground-moves", async () => { + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + const enemyOpponent = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.TELEKINESIS); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined(); + expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeDefined(); + + await game.toNextTurn(); + vi.spyOn(allMoves[Moves.MUD_SHOT], "accuracy", "get").mockReturnValue(100); + game.move.select(Moves.MUD_SHOT); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyOpponent.isFullHp()).toBe(true); + }); + + it("Telekinesis can still affect Pokemon that have been transformed into invalid Pokemon", async () => { + game.override.enemyMoveset(Moves.TRANSFORM); + await game.classicMode.startBattle([ Species.DIGLETT ]); + + const enemyOpponent = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.TELEKINESIS); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined(); + expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeDefined(); + expect(enemyOpponent.summonData.speciesForm?.speciesId).toBe(Species.DIGLETT); + }); + + it("Moves like Smack Down and 1000 Arrows remove all effects of Telekinesis from the target Pokemon", async () => { + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + const enemyOpponent = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.TELEKINESIS); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined(); + expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeDefined(); + + await game.toNextTurn(); + game.move.select(Moves.SMACK_DOWN); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeUndefined(); + expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeUndefined(); + }); + + it("Ingrain will remove the floating effect of Telekinesis, but not the 100% hit", async () => { + game.override.enemyMoveset([ Moves.SPLASH, Moves.INGRAIN ]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyOpponent = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.TELEKINESIS); + await game.forceEnemyMove(Moves.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined(); + expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeDefined(); + + await game.toNextTurn(); + vi.spyOn(allMoves[Moves.MUD_SHOT], "accuracy", "get").mockReturnValue(0); + game.move.select(Moves.MUD_SHOT); + await game.forceEnemyMove(Moves.INGRAIN); + await game.phaseInterceptor.to("TurnEndPhase"); + expect(enemyOpponent.getTag(BattlerTagType.TELEKINESIS)).toBeDefined(); + expect(enemyOpponent.getTag(BattlerTagType.INGRAIN)).toBeDefined(); + expect(enemyOpponent.getTag(BattlerTagType.IGNORE_FLYING)).toBeDefined(); + expect(enemyOpponent.getTag(BattlerTagType.FLOATING)).toBeUndefined(); + expect(playerPokemon.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS); + }); +}); diff --git a/src/test/moves/tera_blast.test.ts b/src/test/moves/tera_blast.test.ts index 55d61496297..0ce8a552105 100644 --- a/src/test/moves/tera_blast.test.ts +++ b/src/test/moves/tera_blast.test.ts @@ -32,7 +32,7 @@ describe("Moves - Tera Blast", () => { .battleType("single") .disableCrits() .starterSpecies(Species.FEEBAS) - .moveset([Moves.TERA_BLAST]) + .moveset([ Moves.TERA_BLAST ]) .ability(Abilities.BALL_FETCH) .startingHeldItems([{ name: "TERA_SHARD", type: Type.FIRE }]) .enemySpecies(Species.MAGIKARP) @@ -52,7 +52,7 @@ describe("Moves - Tera Blast", () => { vi.spyOn(enemyPokemon, "apply"); game.move.select(Moves.TERA_BLAST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.SUPER_EFFECTIVE); @@ -64,7 +64,7 @@ describe("Moves - Tera Blast", () => { await game.startBattle(); game.move.select(Moves.TERA_BLAST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(moveToCheck.calculateBattlePower).toHaveReturnedWith(100); @@ -80,7 +80,7 @@ describe("Moves - Tera Blast", () => { vi.spyOn(enemyPokemon, "isTerastallized").mockReturnValue(true); game.move.select(Moves.TERA_BLAST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEffectPhase"); expect(enemyPokemon.apply).toHaveReturnedWith(HitResult.SUPER_EFFECTIVE); @@ -107,7 +107,7 @@ describe("Moves - Tera Blast", () => { const playerPokemon = game.scene.getPlayerPokemon()!; game.move.select(Moves.TERA_BLAST); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(-1); diff --git a/src/test/moves/tera_starstorm.test.ts b/src/test/moves/tera_starstorm.test.ts index 20dbc0b77d6..f0759dd242d 100644 --- a/src/test/moves/tera_starstorm.test.ts +++ b/src/test/moves/tera_starstorm.test.ts @@ -24,7 +24,7 @@ describe("Moves - Tera Starstorm", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.TERA_STARSTORM, Moves.SPLASH]) + .moveset([ Moves.TERA_STARSTORM, Moves.SPLASH ]) .battleType("double") .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH) @@ -35,7 +35,7 @@ describe("Moves - Tera Starstorm", () => { it("changes type to Stellar when used by Terapagos in its Stellar Form", async () => { game.override.battleType("single"); - await game.classicMode.startBattle([Species.TERAPAGOS]); + await game.classicMode.startBattle([ Species.TERAPAGOS ]); const terapagos = game.scene.getPlayerPokemon()!; @@ -49,12 +49,12 @@ describe("Moves - Tera Starstorm", () => { }); it("targets both opponents in a double battle when used by Terapagos in its Stellar Form", async () => { - await game.classicMode.startBattle([Species.MAGIKARP, Species.TERAPAGOS]); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.TERAPAGOS ]); game.move.select(Moves.TERA_STARSTORM, 0, BattlerIndex.ENEMY); game.move.select(Moves.TERA_STARSTORM, 1); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2 ]); const enemyField = game.scene.getEnemyField(); @@ -68,7 +68,7 @@ describe("Moves - Tera Starstorm", () => { }); it("applies the effects when Terapagos in Stellar Form is fused with another Pokemon", async () => { - await game.classicMode.startBattle([Species.TERAPAGOS, Species.CHARMANDER, Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.TERAPAGOS, Species.CHARMANDER, Species.MAGIKARP ]); const fusionedMon = game.scene.getParty()[0]; const magikarp = game.scene.getParty()[2]; diff --git a/src/test/moves/thousand_arrows.test.ts b/src/test/moves/thousand_arrows.test.ts index ad9281dc45e..976b4352ee4 100644 --- a/src/test/moves/thousand_arrows.test.ts +++ b/src/test/moves/thousand_arrows.test.ts @@ -9,7 +9,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Moves - Thousand Arrows", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -30,14 +29,14 @@ describe("Moves - Thousand Arrows", () => { game.override.enemySpecies(Species.TOGETIC); game.override.startingLevel(100); game.override.enemyLevel(100); - game.override.moveset([Moves.THOUSAND_ARROWS]); - game.override.enemyMoveset([Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH]); + game.override.moveset([ Moves.THOUSAND_ARROWS ]); + game.override.enemyMoveset([ Moves.SPLASH, Moves.SPLASH, Moves.SPLASH, Moves.SPLASH ]); }); it( "move should hit and ground Flying-type targets", async () => { - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -60,7 +59,7 @@ describe("Moves - Thousand Arrows", () => { game.override.enemySpecies(Species.SNORLAX); game.override.enemyAbility(Abilities.LEVITATE); - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; @@ -82,17 +81,17 @@ describe("Moves - Thousand Arrows", () => { async () => { game.override.enemySpecies(Species.SNORLAX); - await game.startBattle([Species.ILLUMISE]); + await game.startBattle([ Species.ILLUMISE ]); const enemyPokemon = game.scene.getEnemyPokemon()!; - enemyPokemon.addTag(BattlerTagType.MAGNET_RISEN, undefined, Moves.MAGNET_RISE); + enemyPokemon.addTag(BattlerTagType.FLOATING, undefined, Moves.MAGNET_RISE); game.move.select(Moves.THOUSAND_ARROWS); await game.phaseInterceptor.to(BerryPhase, false); - expect(enemyPokemon.getTag(BattlerTagType.MAGNET_RISEN)).toBeUndefined(); + expect(enemyPokemon.getTag(BattlerTagType.FLOATING)).toBeUndefined(); expect(enemyPokemon.getTag(BattlerTagType.IGNORE_FLYING)).toBeDefined(); expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); } diff --git a/src/test/moves/throat_chop.test.ts b/src/test/moves/throat_chop.test.ts index 2a0ab675b25..24293f8d086 100644 --- a/src/test/moves/throat_chop.test.ts +++ b/src/test/moves/throat_chop.test.ts @@ -32,12 +32,12 @@ describe("Moves - Throat Chop", () => { }); it("prevents the target from using sound-based moves for two turns", async () => { - await game.classicMode.startBattle([Species.MAGIKARP]); + await game.classicMode.startBattle([ Species.MAGIKARP ]); const enemy = game.scene.getEnemyPokemon()!; game.move.select(Moves.GROWL); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); // First turn, move is interrupted await game.phaseInterceptor.to("TurnEndPhase"); @@ -47,7 +47,7 @@ describe("Moves - Throat Chop", () => { await game.toNextTurn(); game.move.select(Moves.GROWL); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MoveEndPhase"); expect(enemy.isFullHp()).toBe(false); diff --git a/src/test/moves/thunder_wave.test.ts b/src/test/moves/thunder_wave.test.ts index 28c5da4717b..03e9ebb94f3 100644 --- a/src/test/moves/thunder_wave.test.ts +++ b/src/test/moves/thunder_wave.test.ts @@ -8,7 +8,6 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - describe("Moves - Thunder Wave", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -28,7 +27,7 @@ describe("Moves - Thunder Wave", () => { game.override .battleType("single") .starterSpecies(Species.PIKACHU) - .moveset([Moves.THUNDER_WAVE]) + .moveset([ Moves.THUNDER_WAVE ]) .enemyMoveset(Moves.SPLASH); }); diff --git a/src/test/moves/tidy_up.test.ts b/src/test/moves/tidy_up.test.ts index 8a3a0f3be76..255967b40ac 100644 --- a/src/test/moves/tidy_up.test.ts +++ b/src/test/moves/tidy_up.test.ts @@ -33,13 +33,13 @@ describe("Moves - Tidy Up", () => { game.override.enemyMoveset(Moves.SPLASH); game.override.starterSpecies(Species.FEEBAS); game.override.ability(Abilities.BALL_FETCH); - game.override.moveset([Moves.TIDY_UP]); + game.override.moveset([ Moves.TIDY_UP ]); game.override.startingLevel(50); }); it("spikes are cleared", async () => { - game.override.moveset([Moves.SPIKES, Moves.TIDY_UP]); - game.override.enemyMoveset([Moves.SPIKES, Moves.SPIKES, Moves.SPIKES, Moves.SPIKES]); + game.override.moveset([ Moves.SPIKES, Moves.TIDY_UP ]); + game.override.enemyMoveset([ Moves.SPIKES, Moves.SPIKES, Moves.SPIKES, Moves.SPIKES ]); await game.classicMode.startBattle(); game.move.select(Moves.SPIKES); @@ -51,8 +51,8 @@ describe("Moves - Tidy Up", () => { }, 20000); it("stealth rocks are cleared", async () => { - game.override.moveset([Moves.STEALTH_ROCK, Moves.TIDY_UP]); - game.override.enemyMoveset([Moves.STEALTH_ROCK, Moves.STEALTH_ROCK, Moves.STEALTH_ROCK, Moves.STEALTH_ROCK]); + game.override.moveset([ Moves.STEALTH_ROCK, Moves.TIDY_UP ]); + game.override.enemyMoveset([ Moves.STEALTH_ROCK, Moves.STEALTH_ROCK, Moves.STEALTH_ROCK, Moves.STEALTH_ROCK ]); await game.classicMode.startBattle(); game.move.select(Moves.STEALTH_ROCK); @@ -63,8 +63,8 @@ describe("Moves - Tidy Up", () => { }, 20000); it("toxic spikes are cleared", async () => { - game.override.moveset([Moves.TOXIC_SPIKES, Moves.TIDY_UP]); - game.override.enemyMoveset([Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES]); + game.override.moveset([ Moves.TOXIC_SPIKES, Moves.TIDY_UP ]); + game.override.enemyMoveset([ Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES, Moves.TOXIC_SPIKES ]); await game.classicMode.startBattle(); game.move.select(Moves.TOXIC_SPIKES); @@ -75,8 +75,8 @@ describe("Moves - Tidy Up", () => { }, 20000); it("sticky webs are cleared", async () => { - game.override.moveset([Moves.STICKY_WEB, Moves.TIDY_UP]); - game.override.enemyMoveset([Moves.STICKY_WEB, Moves.STICKY_WEB, Moves.STICKY_WEB, Moves.STICKY_WEB]); + game.override.moveset([ Moves.STICKY_WEB, Moves.TIDY_UP ]); + game.override.enemyMoveset([ Moves.STICKY_WEB, Moves.STICKY_WEB, Moves.STICKY_WEB, Moves.STICKY_WEB ]); await game.classicMode.startBattle(); @@ -88,8 +88,8 @@ describe("Moves - Tidy Up", () => { }, 20000); it("substitutes are cleared", async () => { - game.override.moveset([Moves.SUBSTITUTE, Moves.TIDY_UP]); - game.override.enemyMoveset([Moves.SUBSTITUTE, Moves.SUBSTITUTE, Moves.SUBSTITUTE, Moves.SUBSTITUTE]); + game.override.moveset([ Moves.SUBSTITUTE, Moves.TIDY_UP ]); + game.override.enemyMoveset([ Moves.SUBSTITUTE, Moves.SUBSTITUTE, Moves.SUBSTITUTE, Moves.SUBSTITUTE ]); await game.classicMode.startBattle(); diff --git a/src/test/moves/torment.test.ts b/src/test/moves/torment.test.ts index f725f2bc34a..b4c9a059db1 100644 --- a/src/test/moves/torment.test.ts +++ b/src/test/moves/torment.test.ts @@ -26,15 +26,15 @@ describe("Moves - Torment", () => { game.override .battleType("single") .enemyAbility(Abilities.BALL_FETCH) - .enemyMoveset([Moves.TORMENT, Moves.SPLASH]) + .enemyMoveset([ Moves.TORMENT, Moves.SPLASH ]) .enemySpecies(Species.SHUCKLE) .enemyLevel(30) - .moveset([Moves.TACKLE]) + .moveset([ Moves.TACKLE ]) .ability(Abilities.BALL_FETCH); }); it("Pokemon should not be able to use the same move consecutively", async () => { - await game.classicMode.startBattle([Species.CHANSEY]); + await game.classicMode.startBattle([ Species.CHANSEY ]); const playerPokemon = game.scene.getPlayerPokemon()!; diff --git a/src/test/moves/toxic.test.ts b/src/test/moves/toxic.test.ts index 2d023c201c1..b146134ae51 100644 --- a/src/test/moves/toxic.test.ts +++ b/src/test/moves/toxic.test.ts @@ -32,7 +32,7 @@ describe("Moves - Toxic", () => { it("should be guaranteed to hit if user is Poison-type", async () => { vi.spyOn(allMoves[Moves.TOXIC], "accuracy", "get").mockReturnValue(0); - await game.classicMode.startBattle([Species.TOXAPEX]); + await game.classicMode.startBattle([ Species.TOXAPEX ]); game.move.select(Moves.TOXIC); await game.phaseInterceptor.to("BerryPhase", false); @@ -42,7 +42,7 @@ describe("Moves - Toxic", () => { it("may miss if user is not Poison-type", async () => { vi.spyOn(allMoves[Moves.TOXIC], "accuracy", "get").mockReturnValue(0); - await game.classicMode.startBattle([Species.UMBREON]); + await game.classicMode.startBattle([ Species.UMBREON ]); game.move.select(Moves.TOXIC); await game.phaseInterceptor.to("BerryPhase", false); @@ -53,10 +53,10 @@ describe("Moves - Toxic", () => { it("should hit semi-invulnerable targets if user is Poison-type", async () => { vi.spyOn(allMoves[Moves.TOXIC], "accuracy", "get").mockReturnValue(0); game.override.enemyMoveset(Moves.FLY); - await game.classicMode.startBattle([Species.TOXAPEX]); + await game.classicMode.startBattle([ Species.TOXAPEX ]); game.move.select(Moves.TOXIC); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase", false); expect(game.scene.getEnemyPokemon()!.status?.effect).toBe(StatusEffect.TOXIC); @@ -65,12 +65,25 @@ describe("Moves - Toxic", () => { it("should miss semi-invulnerable targets if user is not Poison-type", async () => { vi.spyOn(allMoves[Moves.TOXIC], "accuracy", "get").mockReturnValue(-1); game.override.enemyMoveset(Moves.FLY); - await game.classicMode.startBattle([Species.UMBREON]); + await game.classicMode.startBattle([ Species.UMBREON ]); game.move.select(Moves.TOXIC); - await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); await game.phaseInterceptor.to("BerryPhase", false); expect(game.scene.getEnemyPokemon()!.status).toBeUndefined(); }); + + it("moves other than Toxic should not hit semi-invulnerable targets even if user is Poison-type", async () => { + game.override.moveset(Moves.SWIFT); + game.override.enemyMoveset(Moves.FLY); + await game.classicMode.startBattle([ Species.TOXAPEX ]); + + game.move.select(Moves.SWIFT); + await game.setTurnOrder([ BattlerIndex.ENEMY, BattlerIndex.PLAYER ]); + await game.phaseInterceptor.to("BerryPhase", false); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); + }); }); diff --git a/src/test/moves/toxic_spikes.test.ts b/src/test/moves/toxic_spikes.test.ts new file mode 100644 index 00000000000..bac1ccdccd8 --- /dev/null +++ b/src/test/moves/toxic_spikes.test.ts @@ -0,0 +1,136 @@ +import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; +import { StatusEffect } from "#app/data/status-effect"; +import { decrypt, encrypt, GameData, SessionSaveData } from "#app/system/game-data"; +import { Abilities } from "#enums/abilities"; +import { ArenaTagType } from "#enums/arena-tag-type"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +const TIMEOUT = 20 * 1000; + +describe("Moves - Toxic Spikes", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .battleType("single") + .startingWave(5) + .enemySpecies(Species.RATTATA) + .enemyAbility(Abilities.BALL_FETCH) + .ability(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH) + .moveset([ Moves.TOXIC_SPIKES, Moves.SPLASH, Moves.ROAR ]); + }); + + it("should not affect the opponent if they do not switch", async() => { + await game.classicMode.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA ]); + + const enemy = game.scene.getEnemyField()[0]; + + game.move.select(Moves.TOXIC_SPIKES); + await game.phaseInterceptor.to("TurnEndPhase"); + game.move.select(Moves.SPLASH); + await game.phaseInterceptor.to("TurnEndPhase"); + game.doSwitchPokemon(1); + await game.phaseInterceptor.to("TurnEndPhase"); + + expect(enemy.hp).toBe(enemy.getMaxHp()); + expect(enemy.status?.effect).toBeUndefined(); + }, TIMEOUT); + + it("should poison the opponent if they switch into 1 layer", async() => { + await game.classicMode.runToSummon([ Species.MIGHTYENA ]); + + game.move.select(Moves.TOXIC_SPIKES); + await game.phaseInterceptor.to("TurnEndPhase"); + game.move.select(Moves.ROAR); + await game.phaseInterceptor.to("TurnEndPhase"); + + const enemy = game.scene.getEnemyField()[0]; + + expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); + expect(enemy.status?.effect).toBe(StatusEffect.POISON); + }, TIMEOUT); + + it("should badly poison the opponent if they switch into 2 layers", async() => { + await game.classicMode.runToSummon([ Species.MIGHTYENA ]); + + game.move.select(Moves.TOXIC_SPIKES); + await game.phaseInterceptor.to("TurnEndPhase"); + game.move.select(Moves.TOXIC_SPIKES); + await game.phaseInterceptor.to("TurnEndPhase"); + game.move.select(Moves.ROAR); + await game.phaseInterceptor.to("TurnEndPhase"); + + const enemy = game.scene.getEnemyField()[0]; + expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); + expect(enemy.status?.effect).toBe(StatusEffect.TOXIC); + }, TIMEOUT); + + it("should be removed if a grounded poison pokemon switches in", async() => { + game.override.enemySpecies(Species.GRIMER); + await game.classicMode.runToSummon([ Species.MIGHTYENA ]); + + game.move.select(Moves.TOXIC_SPIKES); + await game.phaseInterceptor.to("TurnEndPhase"); + game.move.select(Moves.TOXIC_SPIKES); + await game.phaseInterceptor.to("TurnEndPhase"); + game.move.select(Moves.ROAR); + await game.phaseInterceptor.to("TurnEndPhase"); + + const enemy = game.scene.getEnemyField()[0]; + expect(enemy.hp).toBe(enemy.getMaxHp()); + expect(enemy.status?.effect).toBeUndefined(); + + expect(game.scene.arena.tags.length).toBe(0); + }, TIMEOUT); + + it("shouldn't create multiple layers per use in doubles", async() => { + await game.classicMode.runToSummon([ Species.MIGHTYENA, Species.POOCHYENA ]); + + game.move.select(Moves.TOXIC_SPIKES); + await game.phaseInterceptor.to("TurnEndPhase"); + + const arenaTags = (game.scene.arena.getTagOnSide(ArenaTagType.TOXIC_SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag); + expect(arenaTags.tagType).toBe(ArenaTagType.TOXIC_SPIKES); + expect(arenaTags.layers).toBe(1); + }, TIMEOUT); + + it("should persist through reload", async() => { + game.override.startingWave(1); + const scene = game.scene; + const gameData = new GameData(scene); + + await game.classicMode.runToSummon([ Species.MIGHTYENA ]); + + game.move.select(Moves.TOXIC_SPIKES); + await game.phaseInterceptor.to("TurnEndPhase"); + game.move.select(Moves.SPLASH); + await game.doKillOpponents(); + await game.phaseInterceptor.to("BattleEndPhase"); + await game.toNextWave(); + + const sessionData : SessionSaveData = gameData["getSessionSaveData"](game.scene); + localStorage.setItem("sessionTestData", encrypt(JSON.stringify(sessionData), true)); + const recoveredData : SessionSaveData = gameData.parseSessionData(decrypt(localStorage.getItem("sessionTestData")!, true)); + gameData.loadSession(game.scene, 0, recoveredData); + + expect(sessionData.arena.tags).toEqual(recoveredData.arena.tags); + localStorage.removeItem("sessionTestData"); + }, TIMEOUT); +}); diff --git a/src/test/moves/transform.test.ts b/src/test/moves/transform.test.ts index 6686f1fc73b..079fdfa5685 100644 --- a/src/test/moves/transform.test.ts +++ b/src/test/moves/transform.test.ts @@ -76,7 +76,7 @@ describe("Moves - Transform", () => { }, 20000); it("should copy in-battle overridden stats", async () => { - game.override.enemyMoveset([Moves.POWER_SPLIT]); + game.override.enemyMoveset([ Moves.POWER_SPLIT ]); await game.startBattle([ Species.DITTO diff --git a/src/test/moves/triple_arrows.test.ts b/src/test/moves/triple_arrows.test.ts new file mode 100644 index 00000000000..98ad29997df --- /dev/null +++ b/src/test/moves/triple_arrows.test.ts @@ -0,0 +1,60 @@ +import { allMoves, FlinchAttr, StatStageChangeAttr } from "#app/data/move"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import GameManager from "#test/utils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +describe("Moves - Triple Arrows", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + const tripleArrows = allMoves[Moves.TRIPLE_ARROWS]; + const flinchAttr = tripleArrows.getAttrs(FlinchAttr)[0]; + const defDropAttr = tripleArrows.getAttrs(StatStageChangeAttr)[0]; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .ability(Abilities.BALL_FETCH) + .moveset([ Moves.TRIPLE_ARROWS ]) + .battleType("single") + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.STURDY) + .enemyMoveset(Moves.SPLASH); + + vi.spyOn(flinchAttr, "getMoveChance"); + vi.spyOn(defDropAttr, "getMoveChance"); + }); + + it("has a 30% flinch chance and 50% defense drop chance", async () => { + await game.classicMode.startBattle([ Species.FEEBAS ]); + + game.move.select(Moves.TRIPLE_ARROWS); + await game.phaseInterceptor.to("BerryPhase"); + + expect(flinchAttr.getMoveChance).toHaveReturnedWith(30); + expect(defDropAttr.getMoveChance).toHaveReturnedWith(50); + }); + + it("is affected normally by Serene Grace", async () => { + game.override.ability(Abilities.SERENE_GRACE); + await game.classicMode.startBattle([ Species.FEEBAS ]); + + game.move.select(Moves.TRIPLE_ARROWS); + await game.phaseInterceptor.to("BerryPhase"); + + expect(flinchAttr.getMoveChance).toHaveReturnedWith(60); + expect(defDropAttr.getMoveChance).toHaveReturnedWith(100); + }); +}); diff --git a/src/test/moves/u_turn.test.ts b/src/test/moves/u_turn.test.ts index c4b6ae2497f..b995c20f503 100644 --- a/src/test/moves/u_turn.test.ts +++ b/src/test/moves/u_turn.test.ts @@ -29,7 +29,7 @@ describe("Moves - U-turn", () => { .enemySpecies(Species.GENGAR) .startingLevel(90) .startingWave(97) - .moveset([Moves.U_TURN]) + .moveset([ Moves.U_TURN ]) .enemyMoveset(Moves.SPLASH) .disableCrits(); }); @@ -96,4 +96,23 @@ describe("Moves - U-turn", () => { expect(game.scene.getEnemyPokemon()!.battleData.abilityRevealed).toBe(true); // proxy for asserting ability activated expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase"); }, 20000); + + it("still forces a switch if u-turn KO's the opponent", async () => { + game.override.startingLevel(1000); // Ensure that U-Turn KO's the opponent + await game.classicMode.startBattle([ + Species.RAICHU, + Species.SHUCKLE + ]); + const enemy = game.scene.getEnemyPokemon()!; + + // KO the opponent with U-Turn + game.move.select(Moves.U_TURN); + game.doSelectPartyPokemon(1); + await game.phaseInterceptor.to(TurnEndPhase); + expect(enemy.isFainted()).toBe(true); + + // Check that U-Turn forced a switch + expect(game.phaseInterceptor.log).toContain("SwitchSummonPhase"); + expect(game.scene.getPlayerPokemon()!.species.speciesId).toBe(Species.SHUCKLE); + }); }); diff --git a/src/test/moves/whirlwind.test.ts b/src/test/moves/whirlwind.test.ts index a591a3cd6c5..cc31b2591a2 100644 --- a/src/test/moves/whirlwind.test.ts +++ b/src/test/moves/whirlwind.test.ts @@ -1,12 +1,11 @@ -import { BattlerIndex } from "#app/battle"; -import { allMoves } from "#app/data/move"; import { BattlerTagType } from "#app/enums/battler-tag-type"; +import { MoveResult } from "#app/field/pokemon"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Moves - Whirlwind", () => { let phaserGame: Phaser.Game; @@ -36,18 +35,15 @@ describe("Moves - Whirlwind", () => { { move: Moves.BOUNCE, name: "Bounce" }, { move: Moves.SKY_DROP, name: "Sky Drop" }, ])("should not hit a flying target: $name (=$move)", async ({ move }) => { - game.override.moveset([move]); - await game.classicMode.startBattle([Species.STARAPTOR]); + game.override.moveset([ move ]); + await game.classicMode.startBattle([ Species.STARAPTOR ]); const staraptor = game.scene.getPlayerPokemon()!; - const whirlwind = allMoves[Moves.WHIRLWIND]; - vi.spyOn(whirlwind, "getFailedText"); game.move.select(move); - await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.toNextTurn(); expect(staraptor.findTag((t) => t.tagType === BattlerTagType.FLYING)).toBeDefined(); - expect(whirlwind.getFailedText).toHaveBeenCalledOnce(); + expect(game.scene.getEnemyPokemon()!.getLastXMoves(1)[0].result).toBe(MoveResult.MISS); }); }); diff --git a/src/test/moves/wide_guard.test.ts b/src/test/moves/wide_guard.test.ts index 9ddd8905ff6..c25a700c981 100644 --- a/src/test/moves/wide_guard.test.ts +++ b/src/test/moves/wide_guard.test.ts @@ -9,7 +9,6 @@ import { BerryPhase } from "#app/phases/berry-phase"; import { CommandPhase } from "#app/phases/command-phase"; - describe("Moves - Wide Guard", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -29,10 +28,10 @@ describe("Moves - Wide Guard", () => { game.override.battleType("double"); - game.override.moveset([Moves.WIDE_GUARD, Moves.SPLASH, Moves.SURF]); + game.override.moveset([ Moves.WIDE_GUARD, Moves.SPLASH, Moves.SURF ]); game.override.enemySpecies(Species.SNORLAX); - game.override.enemyMoveset([Moves.SWIFT]); + game.override.enemyMoveset([ Moves.SWIFT ]); game.override.enemyAbility(Abilities.INSOMNIA); game.override.startingLevel(100); @@ -42,7 +41,7 @@ describe("Moves - Wide Guard", () => { test( "should protect the user and allies from multi-target attack moves", async () => { - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerField(); @@ -61,9 +60,9 @@ describe("Moves - Wide Guard", () => { test( "should protect the user and allies from multi-target status moves", async () => { - game.override.enemyMoveset([Moves.GROWL]); + game.override.enemyMoveset([ Moves.GROWL ]); - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerField(); @@ -82,9 +81,9 @@ describe("Moves - Wide Guard", () => { test( "should not protect the user and allies from single-target moves", async () => { - game.override.enemyMoveset([Moves.TACKLE]); + game.override.enemyMoveset([ Moves.TACKLE ]); - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerField(); @@ -103,9 +102,9 @@ describe("Moves - Wide Guard", () => { test( "should protect the user from its ally's multi-target move", async () => { - game.override.enemyMoveset([Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH ]); - await game.startBattle([Species.CHARIZARD, Species.BLASTOISE]); + await game.startBattle([ Species.CHARIZARD, Species.BLASTOISE ]); const leadPokemon = game.scene.getPlayerField(); const enemyPokemon = game.scene.getEnemyField(); diff --git a/src/test/mystery-encounter/encounter-test-utils.ts b/src/test/mystery-encounter/encounter-test-utils.ts index 9fb2504c02b..f95a442d4c2 100644 --- a/src/test/mystery-encounter/encounter-test-utils.ts +++ b/src/test/mystery-encounter/encounter-test-utils.ts @@ -97,20 +97,20 @@ export async function runSelectMysteryEncounterOption(game: GameManager, optionN uiHandler.unblockInput(); // input are blocked by 1s to prevent accidental input. Tests need to handle that switch (optionNo) { - default: - case 1: + default: + case 1: // no movement needed. Default cursor position - break; - case 2: - uiHandler.processInput(Button.RIGHT); - break; - case 3: - uiHandler.processInput(Button.DOWN); - break; - case 4: - uiHandler.processInput(Button.RIGHT); - uiHandler.processInput(Button.DOWN); - break; + break; + case 2: + uiHandler.processInput(Button.RIGHT); + break; + case 3: + uiHandler.processInput(Button.DOWN); + break; + case 4: + uiHandler.processInput(Button.RIGHT); + uiHandler.processInput(Button.DOWN); + break; } if (!isNullOrUndefined(secondaryOptionSelect?.pokemonNo)) { diff --git a/src/test/mystery-encounter/encounters/a-trainers-test-encounter.test.ts b/src/test/mystery-encounter/encounters/a-trainers-test-encounter.test.ts index 6078e136ccb..7d783958422 100644 --- a/src/test/mystery-encounter/encounters/a-trainers-test-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/a-trainers-test-encounter.test.ts @@ -16,9 +16,10 @@ import { EggTier } from "#enums/egg-type"; import { CommandPhase } from "#app/phases/command-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { PartyHealPhase } from "#app/phases/party-heal-phase"; +import i18next from "i18next"; const namespace = "mysteryEncounters/aTrainersTest"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -40,10 +41,10 @@ describe("A Trainer's Test - Mystery Encounter", () => { game.override.disableTrainerWaves(); const biomeMap = new Map([ - [Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.VOLCANO, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]); HUMAN_TRANSITABLE_BIOMES.forEach(biome => { - biomeMap.set(biome, [MysteryEncounterType.A_TRAINERS_TEST]); + biomeMap.set(biome, [ MysteryEncounterType.A_TRAINERS_TEST ]); }); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap); }); @@ -106,7 +107,8 @@ describe("A Trainer's Test - Mystery Encounter", () => { expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(enemyField.length).toBe(1); expect(scene.currentBattle.trainer).toBeDefined(); - expect(["trainerNames:buck", "trainerNames:cheryl", "trainerNames:marley", "trainerNames:mira", "trainerNames:riley"].includes(scene.currentBattle.trainer!.config.name)).toBeTruthy(); + expect([ i18next.t("trainerNames:buck"), i18next.t("trainerNames:cheryl"), i18next.t("trainerNames:marley"), i18next.t("trainerNames:mira"), i18next.t("trainerNames:riley") ] + .map(name => name.toLowerCase()).includes(scene.currentBattle.trainer!.config.name)).toBeTruthy(); expect(enemyField[0]).toBeDefined(); }); @@ -126,7 +128,7 @@ describe("A Trainer's Test - Mystery Encounter", () => { expect(eggsAfter).toBeDefined(); expect(eggsBeforeLength + 1).toBe(eggsAfter.length); const eggTier = eggsAfter[eggsAfter.length - 1].tier; - expect(eggTier === EggTier.ULTRA || eggTier === EggTier.MASTER).toBeTruthy(); + expect(eggTier === EggTier.EPIC || eggTier === EggTier.LEGENDARY).toBeTruthy(); }); }); @@ -174,7 +176,7 @@ describe("A Trainer's Test - Mystery Encounter", () => { expect(eggsAfter).toBeDefined(); expect(eggsBeforeLength + 1).toBe(eggsAfter.length); const eggTier = eggsAfter[eggsAfter.length - 1].tier; - expect(eggTier).toBe(EggTier.GREAT); + expect(eggTier).toBe(EggTier.RARE); }); it("should leave encounter without battle", async () => { diff --git a/src/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts b/src/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts index 99d845c992d..a72a9fbb5a3 100644 --- a/src/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts @@ -16,9 +16,10 @@ import { Moves } from "#enums/moves"; import { CommandPhase } from "#app/phases/command-phase"; import { MovePhase } from "#app/phases/move-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; +import i18next from "i18next"; const namespace = "mysteryEncounters/absoluteAvarice"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.PLAINS; const defaultWave = 45; @@ -41,8 +42,8 @@ describe("Absolute Avarice - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.PLAINS, [MysteryEncounterType.ABSOLUTE_AVARICE]], - [Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.PLAINS, [ MysteryEncounterType.ABSOLUTE_AVARICE ]], + [ Biome.VOLCANO, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]) ); }); @@ -84,7 +85,7 @@ describe("Absolute Avarice - Mystery Encounter", () => { it("should spawn if player has enough berries", async () => { game.override.mysteryEncounterTier(MysteryEncounterTier.GREAT); - game.override.startingHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}]); + game.override.startingHeldItems([{ name: "BERRY", count: 2, type: BerryType.SITRUS }, { name: "BERRY", count: 3, type: BerryType.GANLON }]); await game.runToMysteryEncounter(); @@ -92,7 +93,7 @@ describe("Absolute Avarice - Mystery Encounter", () => { }); it("should remove all player's berries at the start of the encounter", async () => { - game.override.startingHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}]); + game.override.startingHeldItems([{ name: "BERRY", count: 2, type: BerryType.SITRUS }, { name: "BERRY", count: 3, type: BerryType.GANLON }]); await game.runToMysteryEncounter(MysteryEncounterType.ABSOLUTE_AVARICE, defaultParty); @@ -128,7 +129,7 @@ describe("Absolute Avarice - Mystery Encounter", () => { expect(enemyField[0].species.speciesId).toBe(Species.GREEDENT); const moveset = enemyField[0].moveset.map(m => m?.moveId); expect(moveset?.length).toBe(4); - expect(moveset).toEqual([Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH]); + expect(moveset).toEqual([ Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.CRUNCH ]); const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]); expect(movePhases.length).toBe(1); @@ -146,7 +147,7 @@ describe("Absolute Avarice - Mystery Encounter", () => { const pokemonId = partyPokemon.id; const pokemonItems = scene.findModifiers(m => m instanceof PokemonHeldItemModifier && (m as PokemonHeldItemModifier).pokemonId === pokemonId, true) as PokemonHeldItemModifier[]; - const revSeed = pokemonItems.find(i => i.type.name === "modifierType:ModifierType.REVIVER_SEED.name"); + const revSeed = pokemonItems.find(i => i.type.name === i18next.t("modifierType:ModifierType.REVIVER_SEED.name")); expect(revSeed).toBeDefined; expect(revSeed?.stackCount).toBe(1); } @@ -169,8 +170,8 @@ describe("Absolute Avarice - Mystery Encounter", () => { }); }); - it("Should return 3 (2/5ths floored) berries if 8 were stolen", {retry: 5}, async () => { - game.override.startingHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}, {name: "BERRY", count: 3, type: BerryType.APICOT}]); + it("Should return 3 (2/5ths floored) berries if 8 were stolen", { retry: 5 }, async () => { + game.override.startingHeldItems([{ name: "BERRY", count: 2, type: BerryType.SITRUS }, { name: "BERRY", count: 3, type: BerryType.GANLON }, { name: "BERRY", count: 3, type: BerryType.APICOT }]); await game.runToMysteryEncounter(MysteryEncounterType.ABSOLUTE_AVARICE, defaultParty); @@ -185,8 +186,8 @@ describe("Absolute Avarice - Mystery Encounter", () => { expect(berryCountAfter).toBe(3); }); - it("Should return 2 (2/5ths floored) berries if 7 were stolen", {retry: 5}, async () => { - game.override.startingHeldItems([{name: "BERRY", count: 2, type: BerryType.SITRUS}, {name: "BERRY", count: 3, type: BerryType.GANLON}, {name: "BERRY", count: 2, type: BerryType.APICOT}]); + it("Should return 2 (2/5ths floored) berries if 7 were stolen", { retry: 5 }, async () => { + game.override.startingHeldItems([{ name: "BERRY", count: 2, type: BerryType.SITRUS }, { name: "BERRY", count: 3, type: BerryType.GANLON }, { name: "BERRY", count: 2, type: BerryType.APICOT }]); await game.runToMysteryEncounter(MysteryEncounterType.ABSOLUTE_AVARICE, defaultParty); @@ -239,7 +240,7 @@ describe("Absolute Avarice - Mystery Encounter", () => { expect(greedent.species.speciesId).toBe(Species.GREEDENT); const moveset = greedent.moveset.map(m => m?.moveId); expect(moveset?.length).toBe(4); - expect(moveset).toEqual([Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.SLACK_OFF]); + expect(moveset).toEqual([ Moves.THRASH, Moves.BODY_PRESS, Moves.STUFF_CHEEKS, Moves.SLACK_OFF ]); }); it("should leave encounter without battle", async () => { diff --git a/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts b/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts index 06492cae0d2..af9951938b7 100644 --- a/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts @@ -17,10 +17,12 @@ import { getPokemonSpecies } from "#app/data/pokemon-species"; import { Moves } from "#enums/moves"; import { TempExtraModifierModifier } from "#app/modifier/modifier"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; +import i18next from "i18next"; +import { Abilities } from "#enums/abilities"; const namespace = "mysteryEncounters/anOfferYouCantRefuse"; /** Gyarados for Indimidate */ -const defaultParty = [Species.GYARADOS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.GYARADOS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -36,16 +38,17 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => { beforeEach(async () => { game = new GameManager(phaserGame); scene = game.scene; - game.override.mysteryEncounterChance(100); - game.override.startingWave(defaultWave); - game.override.startingBiome(defaultBiome); - game.override.disableTrainerWaves(); + game.override.mysteryEncounterChance(100) + .startingWave(defaultWave) + .startingBiome(defaultBiome) + .disableTrainerWaves() + .ability(Abilities.INTIMIDATE); // Extortion ability const biomeMap = new Map([ - [Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.VOLCANO, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]); HUMAN_TRANSITABLE_BIOMES.forEach(biome => { - biomeMap.set(biome, [MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE]); + biomeMap.set(biome, [ MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE ]); }); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap); }); @@ -93,8 +96,8 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => { expect(AnOfferYouCantRefuseEncounter.dialogueTokens?.strongestPokemon).toBeDefined(); expect(AnOfferYouCantRefuseEncounter.dialogueTokens?.price).toBeDefined(); - expect(AnOfferYouCantRefuseEncounter.dialogueTokens?.option2PrimaryAbility).toBe("ability:intimidate.name"); - expect(AnOfferYouCantRefuseEncounter.dialogueTokens?.moveOrAbility).toBe("ability:intimidate.name"); + expect(AnOfferYouCantRefuseEncounter.dialogueTokens?.option2PrimaryAbility).toBe(i18next.t("ability:intimidate.name")); + expect(AnOfferYouCantRefuseEncounter.dialogueTokens?.moveOrAbility).toBe(i18next.t("ability:intimidate.name")); expect(AnOfferYouCantRefuseEncounter.misc.pokemon instanceof PlayerPokemon).toBeTruthy(); expect(AnOfferYouCantRefuseEncounter.misc?.price?.toString()).toBe(AnOfferYouCantRefuseEncounter.dialogueTokens?.price); expect(onInitResult).toBe(true); @@ -194,10 +197,11 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => { }); it("should award EXP to a pokemon with a move in EXTORTION_MOVES", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, [Species.ABRA]); + game.override.ability(Abilities.SYNCHRONIZE); // Not an extortion ability, so we can test extortion move + await game.runToMysteryEncounter(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, [ Species.ABRA ]); const party = scene.getParty(); const abra = party.find((pkm) => pkm.species.speciesId === Species.ABRA)!; - abra.moveset = [new PokemonMove(Moves.BEAT_UP)]; + abra.moveset = [ new PokemonMove(Moves.BEAT_UP) ]; const expBefore = abra.exp; await runMysteryEncounterToEnd(game, 2); diff --git a/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts b/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts index 225c06483fa..bfa3d428bc0 100644 --- a/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/berries-abound-encounter.test.ts @@ -20,7 +20,7 @@ import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { Abilities } from "#enums/abilities"; const namespace = "mysteryEncounters/berriesAbound"; -const defaultParty = [Species.PYUKUMUKU, Species.MAGIKARP, Species.PIKACHU]; +const defaultParty = [ Species.PYUKUMUKU, Species.MAGIKARP, Species.PIKACHU ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -48,7 +48,7 @@ describe("Berries Abound - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.BERRIES_ABOUND]], + [ Biome.CAVE, [ MysteryEncounterType.BERRIES_ABOUND ]], ]) ); }); @@ -176,10 +176,12 @@ describe("Berries Abound - Mystery Encounter", () => { const encounterTextSpy = vi.spyOn(EncounterDialogueUtils, "showEncounterText"); await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty); + scene.getParty().forEach(pkm => { + vi.spyOn(pkm, "getStat").mockReturnValue(1); // for ease return for every stat + }); + const config = game.scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]; const speciesToSpawn = config.pokemonConfigs?.[0].species.speciesId; - // Setting enemy's level arbitrarily high to outspeed - config.pokemonConfigs![0].dataSource!.level = 1000; await runMysteryEncounterToEnd(game, 2, undefined, true); @@ -189,7 +191,7 @@ describe("Berries Abound - Mystery Encounter", () => { expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); // Should be enraged - expect(enemyField[0].summonData.statStages).toEqual([0, 1, 0, 1, 1, 0, 0]); + expect(enemyField[0].summonData.statStages).toEqual([ 0, 1, 0, 1, 1, 0, 0 ]); expect(encounterTextSpy).toHaveBeenCalledWith(expect.any(BattleScene), `${namespace}:option.2.selected_bad`); }); @@ -198,10 +200,12 @@ describe("Berries Abound - Mystery Encounter", () => { const encounterTextSpy = vi.spyOn(EncounterDialogueUtils, "showEncounterText"); await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty); + scene.getParty().forEach(pkm => { + vi.spyOn(pkm, "getStat").mockReturnValue(1); // for ease return for every stat + }); + const config = game.scene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]; const speciesToSpawn = config.pokemonConfigs?.[0].species.speciesId; - // Setting enemy's level arbitrarily high to outspeed - config.pokemonConfigs![0].dataSource!.level = 1000; await runMysteryEncounterToEnd(game, 2, undefined, true); @@ -211,7 +215,7 @@ describe("Berries Abound - Mystery Encounter", () => { expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); // Should be enraged - expect(enemyField[0].summonData.statStages).toEqual([1, 1, 1, 1, 1, 0, 0]); + expect(enemyField[0].summonData.statStages).toEqual([ 1, 1, 1, 1, 1, 0, 0 ]); expect(encounterTextSpy).toHaveBeenCalledWith(expect.any(BattleScene), `${namespace}:option.2.selected_bad`); }); diff --git a/src/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts b/src/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts index bdf0dc3c307..0dc02e03c6d 100644 --- a/src/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts @@ -22,7 +22,7 @@ import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; const namespace = "mysteryEncounters/bugTypeSuperfan"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.WEEDLE]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.WEEDLE ]; const defaultBiome = Biome.CAVE; const defaultWave = 24; @@ -169,7 +169,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.BUG_TYPE_SUPERFAN]], + [ Biome.CAVE, [ MysteryEncounterType.BUG_TYPE_SUPERFAN ]], ]) ); }); @@ -405,7 +405,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { }); it("should NOT be selectable if the player doesn't have any Bug types", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.ABRA]); + await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [ Species.ABRA ]); await game.phaseInterceptor.to(MysteryEncounterPhase, false); const encounterPhase = scene.getCurrentPhase(); @@ -438,7 +438,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { }); it("should proceed to rewards screen with 2-3 Bug Types reward options", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.BUTTERFREE, Species.BEEDRILL]); + await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [ Species.BUTTERFREE, Species.BEEDRILL ]); await runMysteryEncounterToEnd(game, 2); expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); @@ -453,7 +453,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { }); it("should proceed to rewards screen with 4-5 Bug Types reward options", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.BUTTERFREE, Species.BEEDRILL, Species.GALVANTULA, Species.VOLCARONA]); + await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [ Species.BUTTERFREE, Species.BEEDRILL, Species.GALVANTULA, Species.VOLCARONA ]); await runMysteryEncounterToEnd(game, 2); expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); @@ -468,7 +468,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { }); it("should proceed to rewards screen with 6 Bug Types reward options (including form change item)", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.BUTTERFREE, Species.BEEDRILL, Species.GALVANTULA, Species.VOLCARONA, Species.ANORITH, Species.GENESECT]); + await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [ Species.BUTTERFREE, Species.BEEDRILL, Species.GALVANTULA, Species.VOLCARONA, Species.ANORITH, Species.GENESECT ]); await runMysteryEncounterToEnd(game, 2); expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); @@ -536,8 +536,8 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { }); it("should remove the gifted item and proceed to rewards screen", async () => { - game.override.startingHeldItems([{name: "GRIP_CLAW", count: 1}]); - await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.BUTTERFREE]); + game.override.startingHeldItems([{ name: "GRIP_CLAW", count: 1 }]); + await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [ Species.BUTTERFREE ]); const gripClawCountBefore = scene.findModifier(m => m instanceof ContactHeldItemTransferChanceModifier)?.stackCount ?? 0; @@ -557,10 +557,10 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { }); it("should leave encounter without battle", async () => { - game.override.startingHeldItems([{name: "GRIP_CLAW", count: 1}]); + game.override.startingHeldItems([{ name: "GRIP_CLAW", count: 1 }]); const leaveEncounterWithoutBattleSpy = vi.spyOn(encounterPhaseUtils, "leaveEncounterWithoutBattle"); - await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [Species.BUTTERFREE]); + await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [ Species.BUTTERFREE ]); await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); expect(leaveEncounterWithoutBattleSpy).toBeCalled(); diff --git a/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts b/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts index e8c78eb09af..7733a4e0a7c 100644 --- a/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/clowning-around-encounter.test.ts @@ -34,7 +34,7 @@ import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { NewBattlePhase } from "#app/phases/new-battle-phase"; const namespace = "mysteryEncounters/clowningAround"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -57,7 +57,7 @@ describe("Clowning Around - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.CLOWNING_AROUND]], + [ Biome.CAVE, [ MysteryEncounterType.CLOWNING_AROUND ]], ]) ); }); @@ -114,13 +114,13 @@ describe("Clowning Around - Mystery Encounter", () => { expect(config.pokemonConfigs?.[0]).toEqual({ species: getPokemonSpecies(Species.MR_MIME), isBoss: true, - moveSet: [Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC] + moveSet: [ Moves.TEETER_DANCE, Moves.ALLY_SWITCH, Moves.DAZZLING_GLEAM, Moves.PSYCHIC ] }); expect(config.pokemonConfigs?.[1]).toEqual({ species: getPokemonSpecies(Species.BLACEPHALON), mysteryEncounterPokemonData: expect.anything(), isBoss: true, - moveSet: [Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN] + moveSet: [ Moves.TRICK, Moves.HYPNOSIS, Moves.SHADOW_BALL, Moves.MIND_BLOWN ] }); expect(config.pokemonConfigs?.[1].mysteryEncounterPokemonData?.types.length).toBe(2); expect([ @@ -173,9 +173,9 @@ describe("Clowning Around - Mystery Encounter", () => { expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(enemyField.length).toBe(2); expect(enemyField[0].species.speciesId).toBe(Species.MR_MIME); - expect(enemyField[0].moveset).toEqual([new PokemonMove(Moves.TEETER_DANCE), new PokemonMove(Moves.ALLY_SWITCH), new PokemonMove(Moves.DAZZLING_GLEAM), new PokemonMove(Moves.PSYCHIC)]); + expect(enemyField[0].moveset).toEqual([ new PokemonMove(Moves.TEETER_DANCE), new PokemonMove(Moves.ALLY_SWITCH), new PokemonMove(Moves.DAZZLING_GLEAM), new PokemonMove(Moves.PSYCHIC) ]); expect(enemyField[1].species.speciesId).toBe(Species.BLACEPHALON); - expect(enemyField[1].moveset).toEqual([new PokemonMove(Moves.TRICK), new PokemonMove(Moves.HYPNOSIS), new PokemonMove(Moves.SHADOW_BALL), new PokemonMove(Moves.MIND_BLOWN)]); + expect(enemyField[1].moveset).toEqual([ new PokemonMove(Moves.TRICK), new PokemonMove(Moves.HYPNOSIS), new PokemonMove(Moves.SHADOW_BALL), new PokemonMove(Moves.MIND_BLOWN) ]); // Should have used moves pre-battle const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]); @@ -251,14 +251,14 @@ describe("Clowning Around - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty); // Set some moves on party for attack type booster generation - scene.getParty()[0].moveset = [new PokemonMove(Moves.TACKLE), new PokemonMove(Moves.THIEF)]; + scene.getParty()[0].moveset = [ new PokemonMove(Moves.TACKLE), new PokemonMove(Moves.THIEF) ]; // 2 Sitrus Berries on lead scene.modifiers = []; - let itemType = generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType; + let itemType = generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ]) as PokemonHeldItemModifierType; await addItemToPokemon(scene, scene.getParty()[0], 2, itemType); // 2 Ganlon Berries on lead - itemType = generateModifierType(scene, modifierTypes.BERRY, [BerryType.GANLON]) as PokemonHeldItemModifierType; + itemType = generateModifierType(scene, modifierTypes.BERRY, [ BerryType.GANLON ]) as PokemonHeldItemModifierType; await addItemToPokemon(scene, scene.getParty()[0], 2, itemType); // 5 Golden Punch on lead (ultra) itemType = generateModifierType(scene, modifierTypes.GOLDEN_PUNCH) as PokemonHeldItemModifierType; @@ -333,9 +333,9 @@ describe("Clowning Around - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty); // Same type moves on lead - scene.getParty()[0].moveset = [new PokemonMove(Moves.ICE_BEAM), new PokemonMove(Moves.SURF)]; + scene.getParty()[0].moveset = [ new PokemonMove(Moves.ICE_BEAM), new PokemonMove(Moves.SURF) ]; // Different type moves on second - scene.getParty()[1].moveset = [new PokemonMove(Moves.GRASS_KNOT), new PokemonMove(Moves.ELECTRO_BALL)]; + scene.getParty()[1].moveset = [ new PokemonMove(Moves.GRASS_KNOT), new PokemonMove(Moves.ELECTRO_BALL) ]; // No moves on third scene.getParty()[2].moveset = []; await runMysteryEncounterToEnd(game, 3); @@ -346,11 +346,11 @@ describe("Clowning Around - Mystery Encounter", () => { expect(leadTypesAfter.length).toBe(2); expect(leadTypesAfter[0]).toBe(Type.WATER); - expect([Type.WATER, Type.ICE].includes(leadTypesAfter[1])).toBeFalsy(); + expect([ Type.WATER, Type.ICE ].includes(leadTypesAfter[1])).toBeFalsy(); expect(secondaryTypesAfter.length).toBe(2); expect(secondaryTypesAfter[0]).toBe(Type.GHOST); - expect([Type.GHOST, Type.POISON].includes(secondaryTypesAfter[1])).toBeFalsy(); - expect([Type.GRASS, Type.ELECTRIC].includes(secondaryTypesAfter[1])).toBeTruthy(); + expect([ Type.GHOST, Type.POISON ].includes(secondaryTypesAfter[1])).toBeFalsy(); + expect([ Type.GRASS, Type.ELECTRIC ].includes(secondaryTypesAfter[1])).toBeTruthy(); expect(thirdTypesAfter.length).toBe(2); expect(thirdTypesAfter[0]).toBe(Type.PSYCHIC); expect(secondaryTypesAfter[1]).not.toBe(Type.PSYCHIC); diff --git a/src/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts b/src/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts index 107bc4f3c67..47625541160 100644 --- a/src/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts @@ -21,7 +21,7 @@ import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { LearnMovePhase } from "#app/phases/learn-move-phase"; const namespace = "mysteryEncounters/dancingLessons"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.PLAINS; const defaultWave = 45; @@ -44,8 +44,8 @@ describe("Dancing Lessons - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.PLAINS, [MysteryEncounterType.DANCING_LESSONS]], - [Biome.SPACE, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.PLAINS, [ MysteryEncounterType.DANCING_LESSONS ]], + [ Biome.SPACE, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]) ); }); @@ -107,7 +107,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(Species.ORICORIO); - expect(enemyField[0].summonData.statStages).toEqual([1, 1, 1, 1, 0, 0, 0]); + expect(enemyField[0].summonData.statStages).toEqual([ 1, 1, 1, 1, 0, 0, 0 ]); const moveset = enemyField[0].moveset.map(m => m?.moveId); expect(moveset.some(m => m === Moves.REVELATION_DANCE)).toBeTruthy(); @@ -197,8 +197,8 @@ describe("Dancing Lessons - Mystery Encounter", () => { it("should add Oricorio to the party", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); const partyCountBefore = scene.getParty().length; - scene.getParty()[0].moveset = [new PokemonMove(Moves.DRAGON_DANCE)]; - await runMysteryEncounterToEnd(game, 3, {pokemonNo: 1, optionNo: 1}); + scene.getParty()[0].moveset = [ new PokemonMove(Moves.DRAGON_DANCE) ]; + await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); const partyCountAfter = scene.getParty().length; expect(partyCountBefore + 1).toBe(partyCountAfter); @@ -236,8 +236,8 @@ describe("Dancing Lessons - Mystery Encounter", () => { const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); - scene.getParty()[0].moveset = [new PokemonMove(Moves.DRAGON_DANCE)]; - await runMysteryEncounterToEnd(game, 3, {pokemonNo: 1, optionNo: 1}); + scene.getParty()[0].moveset = [ new PokemonMove(Moves.DRAGON_DANCE) ]; + await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); expect(leaveEncounterWithoutBattleSpy).toBeCalled(); }); diff --git a/src/test/mystery-encounter/encounters/delibirdy-encounter.test.ts b/src/test/mystery-encounter/encounters/delibirdy-encounter.test.ts index 6003f2737f4..66d628ef82f 100644 --- a/src/test/mystery-encounter/encounters/delibirdy-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/delibirdy-encounter.test.ts @@ -18,7 +18,7 @@ import { modifierTypes } from "#app/modifier/modifier-type"; import { BerryType } from "#enums/berry-type"; const namespace = "mysteryEncounters/delibirdy"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -41,7 +41,7 @@ describe("Delibird-y - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.DELIBIRDY]], + [ Biome.CAVE, [ MysteryEncounterType.DELIBIRDY ]], ]) ); }); @@ -190,13 +190,13 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 2 Sitrus berries on party lead scene.modifiers = []; - const sitrus = generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS])!; + const sitrus = generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ])!; const sitrusMod = sitrus.newModifier(scene.getParty()[0]) as BerryModifier; sitrusMod.stackCount = 2; await scene.addModifier(sitrusMod, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1 }); const sitrusAfter = scene.findModifier(m => m instanceof BerryModifier); const candyJarAfter = scene.findModifier(m => m instanceof LevelIncrementBoosterModifier); @@ -217,7 +217,7 @@ describe("Delibird-y - Mystery Encounter", () => { await scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1 }); const reviverSeedAfter = scene.findModifier(m => m instanceof PokemonInstantReviveModifier); const berryPouchAfter = scene.findModifier(m => m instanceof PreserveBerryModifier); @@ -235,7 +235,7 @@ describe("Delibird-y - Mystery Encounter", () => { const candyJar = generateModifierType(scene, modifierTypes.CANDY_JAR)!.newModifier() as LevelIncrementBoosterModifier; candyJar.stackCount = 99; await scene.addModifier(candyJar, true, false, false, true); - const sitrus = generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS])!; + const sitrus = generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ])!; // Sitrus berries on party const sitrusMod = sitrus.newModifier(scene.getParty()[0]) as BerryModifier; @@ -243,7 +243,7 @@ describe("Delibird-y - Mystery Encounter", () => { await scene.addModifier(sitrusMod, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1 }); const sitrusAfter = scene.findModifier(m => m instanceof BerryModifier); const candyJarAfter = scene.findModifier(m => m instanceof LevelIncrementBoosterModifier); @@ -272,7 +272,7 @@ describe("Delibird-y - Mystery Encounter", () => { await scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1 }); const reviverSeedAfter = scene.findModifier(m => m instanceof PokemonInstantReviveModifier); const healingCharmAfter = scene.findModifier(m => m instanceof PreserveBerryModifier); @@ -324,7 +324,7 @@ describe("Delibird-y - Mystery Encounter", () => { await scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1, optionNo: 1 }); expect(leaveEncounterWithoutBattleSpy).toBeCalled(); }); @@ -358,7 +358,7 @@ describe("Delibird-y - Mystery Encounter", () => { await scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); const soulDewAfter = scene.findModifier(m => m instanceof PokemonNatureWeightModifier); const healingCharmAfter = scene.findModifier(m => m instanceof HealingBoosterModifier); @@ -379,7 +379,7 @@ describe("Delibird-y - Mystery Encounter", () => { await scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); const soulDewAfter = scene.findModifier(m => m instanceof PokemonNatureWeightModifier); const healingCharmAfter = scene.findModifier(m => m instanceof HealingBoosterModifier); @@ -405,7 +405,7 @@ describe("Delibird-y - Mystery Encounter", () => { await scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); const soulDewAfter = scene.findModifier(m => m instanceof PokemonNatureWeightModifier); const healingCharmAfter = scene.findModifier(m => m instanceof HealingBoosterModifier); @@ -458,7 +458,7 @@ describe("Delibird-y - Mystery Encounter", () => { await scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); expect(leaveEncounterWithoutBattleSpy).toBeCalled(); }); diff --git a/src/test/mystery-encounter/encounters/department-store-sale-encounter.test.ts b/src/test/mystery-encounter/encounters/department-store-sale-encounter.test.ts index e36c103b57d..1869a4d3c3c 100644 --- a/src/test/mystery-encounter/encounters/department-store-sale-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/department-store-sale-encounter.test.ts @@ -16,7 +16,7 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; const namespace = "mysteryEncounters/departmentStoreSale"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.PLAINS; const defaultWave = 37; @@ -38,10 +38,10 @@ describe("Department Store Sale - Mystery Encounter", () => { game.override.disableTrainerWaves(); const biomeMap = new Map([ - [Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.VOLCANO, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]); CIVILIZATION_ENCOUNTER_BIOMES.forEach(biome => { - biomeMap.set(biome, [MysteryEncounterType.DEPARTMENT_STORE_SALE]); + biomeMap.set(biome, [ MysteryEncounterType.DEPARTMENT_STORE_SALE ]); }); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap); }); diff --git a/src/test/mystery-encounter/encounters/field-trip-encounter.test.ts b/src/test/mystery-encounter/encounters/field-trip-encounter.test.ts index d8efd340b63..a6f925274c3 100644 --- a/src/test/mystery-encounter/encounters/field-trip-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/field-trip-encounter.test.ts @@ -17,7 +17,7 @@ import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; import i18next from "i18next"; const namespace = "mysteryEncounters/fieldTrip"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -37,11 +37,11 @@ describe("Field Trip - Mystery Encounter", () => { game.override.startingWave(defaultWave); game.override.startingBiome(defaultBiome); game.override.disableTrainerWaves(); - game.override.moveset([Moves.TACKLE, Moves.UPROAR, Moves.SWORDS_DANCE]); + game.override.moveset([ Moves.TACKLE, Moves.UPROAR, Moves.SWORDS_DANCE ]); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.FIELD_TRIP]], + [ Biome.CAVE, [ MysteryEncounterType.FIELD_TRIP ]], ]) ); }); @@ -103,11 +103,11 @@ describe("Field Trip - Mystery Encounter", () => { expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; expect(modifierSelectHandler.options.length).toEqual(5); - expect(modifierSelectHandler.options[0].modifierTypeOption.type.name).toBe("modifierType:TempStatStageBoosterItem.x_attack"); - expect(modifierSelectHandler.options[1].modifierTypeOption.type.name).toBe("modifierType:TempStatStageBoosterItem.x_defense"); - expect(modifierSelectHandler.options[2].modifierTypeOption.type.name).toBe("modifierType:TempStatStageBoosterItem.x_speed"); - expect(modifierSelectHandler.options[3].modifierTypeOption.type.name).toBe("modifierType:ModifierType.DIRE_HIT.name"); - expect(modifierSelectHandler.options[4].modifierTypeOption.type.name).toBe("modifierType:ModifierType.RARER_CANDY.name"); + expect(modifierSelectHandler.options[0].modifierTypeOption.type.name).toBe(i18next.t("modifierType:TempStatStageBoosterItem.x_attack")); + expect(modifierSelectHandler.options[1].modifierTypeOption.type.name).toBe(i18next.t("modifierType:TempStatStageBoosterItem.x_defense")); + expect(modifierSelectHandler.options[2].modifierTypeOption.type.name).toBe(i18next.t("modifierType:TempStatStageBoosterItem.x_speed")); + expect(modifierSelectHandler.options[3].modifierTypeOption.type.name).toBe(i18next.t("modifierType:ModifierType.DIRE_HIT.name")); + expect(modifierSelectHandler.options[4].modifierTypeOption.type.name).toBe(i18next.t("modifierType:ModifierType.RARER_CANDY.name")); }); it("should leave encounter without battle", async () => { @@ -150,11 +150,11 @@ describe("Field Trip - Mystery Encounter", () => { expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; expect(modifierSelectHandler.options.length).toEqual(5); - expect(modifierSelectHandler.options[0].modifierTypeOption.type.name).toBe("modifierType:TempStatStageBoosterItem.x_sp_atk"); - expect(modifierSelectHandler.options[1].modifierTypeOption.type.name).toBe("modifierType:TempStatStageBoosterItem.x_sp_def"); - expect(modifierSelectHandler.options[2].modifierTypeOption.type.name).toBe("modifierType:TempStatStageBoosterItem.x_speed"); - expect(modifierSelectHandler.options[3].modifierTypeOption.type.name).toBe("modifierType:ModifierType.DIRE_HIT.name"); - expect(modifierSelectHandler.options[4].modifierTypeOption.type.name).toBe("modifierType:ModifierType.RARER_CANDY.name"); + expect(modifierSelectHandler.options[0].modifierTypeOption.type.name).toBe(i18next.t("modifierType:TempStatStageBoosterItem.x_sp_atk")); + expect(modifierSelectHandler.options[1].modifierTypeOption.type.name).toBe(i18next.t("modifierType:TempStatStageBoosterItem.x_sp_def")); + expect(modifierSelectHandler.options[2].modifierTypeOption.type.name).toBe(i18next.t("modifierType:TempStatStageBoosterItem.x_speed")); + expect(modifierSelectHandler.options[3].modifierTypeOption.type.name).toBe(i18next.t("modifierType:ModifierType.DIRE_HIT.name")); + expect(modifierSelectHandler.options[4].modifierTypeOption.type.name).toBe(i18next.t("modifierType:ModifierType.RARER_CANDY.name")); }); it("should leave encounter without battle", async () => { @@ -198,12 +198,12 @@ describe("Field Trip - Mystery Encounter", () => { expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; expect(modifierSelectHandler.options.length).toEqual(5); - expect(modifierSelectHandler.options[0].modifierTypeOption.type.name).toBe("modifierType:TempStatStageBoosterItem.x_accuracy"); - expect(modifierSelectHandler.options[1].modifierTypeOption.type.name).toBe("modifierType:TempStatStageBoosterItem.x_speed"); - expect(modifierSelectHandler.options[2].modifierTypeOption.type.name).toBe("modifierType:ModifierType.AddPokeballModifierType.name"); - expect(i18next.t).toHaveBeenCalledWith("modifierType:ModifierType.AddPokeballModifierType.name", expect.objectContaining({ modifierCount: 5 })); - expect(modifierSelectHandler.options[3].modifierTypeOption.type.name).toBe("modifierType:ModifierType.IV_SCANNER.name"); - expect(modifierSelectHandler.options[4].modifierTypeOption.type.name).toBe("modifierType:ModifierType.RARER_CANDY.name"); + expect(modifierSelectHandler.options[0].modifierTypeOption.type.name).toBe(i18next.t("modifierType:TempStatStageBoosterItem.x_accuracy")); + expect(modifierSelectHandler.options[1].modifierTypeOption.type.name).toBe(i18next.t("modifierType:TempStatStageBoosterItem.x_speed")); + expect(modifierSelectHandler.options[2].modifierTypeOption.type.name).toBe(i18next.t("modifierType:ModifierType.AddPokeballModifierType.name", { modifierCount: 5, pokeballName: i18next.t("pokeball:greatBall") })); + expect(i18next.t).toHaveBeenCalledWith(("modifierType:ModifierType.AddPokeballModifierType.name"), expect.objectContaining({ modifierCount: 5 })); + expect(modifierSelectHandler.options[3].modifierTypeOption.type.name).toBe(i18next.t("modifierType:ModifierType.IV_SCANNER.name")); + expect(modifierSelectHandler.options[4].modifierTypeOption.type.name).toBe(i18next.t("modifierType:ModifierType.RARER_CANDY.name")); }); it("should leave encounter without battle", async () => { diff --git a/src/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts b/src/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts index ae556ccebb6..e7dd034c9b0 100644 --- a/src/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts @@ -24,10 +24,11 @@ import { MovePhase } from "#app/phases/move-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { BattlerTagType } from "#enums/battler-tag-type"; import { Abilities } from "#enums/abilities"; +import i18next from "i18next"; const namespace = "mysteryEncounters/fieryFallout"; /** Arcanine and Ninetails for 2 Fire types. Lapras, Gengar, Abra for burnable mon. */ -const defaultParty = [Species.ARCANINE, Species.NINETALES, Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.ARCANINE, Species.NINETALES, Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.VOLCANO; const defaultWave = 56; @@ -51,8 +52,8 @@ describe("Fiery Fallout - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.VOLCANO, [MysteryEncounterType.FIERY_FALLOUT]], - [Biome.MOUNTAIN, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.VOLCANO, [ MysteryEncounterType.FIERY_FALLOUT ]], + [ Biome.MOUNTAIN, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]) ); }); @@ -211,7 +212,7 @@ describe("Fiery Fallout - Mystery Encounter", () => { const burnablePokemon = party.filter((pkm) => pkm.isAllowedInBattle() && !pkm.getTypes().includes(Type.FIRE)); const notBurnablePokemon = party.filter((pkm) => !pkm.isAllowedInBattle() || pkm.getTypes().includes(Type.FIRE)); - expect(scene.currentBattle.mysteryEncounter?.dialogueTokens["burnedPokemon"]).toBe("pokemon:gengar"); + expect(scene.currentBattle.mysteryEncounter?.dialogueTokens["burnedPokemon"]).toBe(i18next.t("pokemon:gengar")); burnablePokemon.forEach((pkm) => { expect(pkm.hp, `${pkm.name} should have received 20% damage: ${pkm.hp} / ${pkm.getMaxHp()} HP`).toBe(pkm.getMaxHp() - Math.floor(pkm.getMaxHp() * 0.2)); }); @@ -268,7 +269,7 @@ describe("Fiery Fallout - Mystery Encounter", () => { }); it("should be disabled if not enough FIRE types are in party", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, [Species.MAGIKARP]); + await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, [ Species.MAGIKARP ]); await game.phaseInterceptor.to(MysteryEncounterPhase, false); const encounterPhase = scene.getCurrentPhase(); diff --git a/src/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts b/src/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts index 20a84281530..d23e7919267 100644 --- a/src/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts @@ -20,7 +20,7 @@ import { CommandPhase } from "#app/phases/command-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; const namespace = "mysteryEncounters/fightOrFlight"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -43,7 +43,7 @@ describe("Fight or Flight - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.FIGHT_OR_FLIGHT]], + [ Biome.CAVE, [ MysteryEncounterType.FIGHT_OR_FLIGHT ]], ]) ); }); @@ -175,7 +175,7 @@ describe("Fight or Flight - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.FIGHT_OR_FLIGHT, defaultParty); // Mock moveset - scene.getParty()[0].moveset = [new PokemonMove(Moves.KNOCK_OFF)]; + scene.getParty()[0].moveset = [ new PokemonMove(Moves.KNOCK_OFF) ]; const item = game.scene.currentBattle.mysteryEncounter!.misc; await runMysteryEncounterToEnd(game, 2); diff --git a/src/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts b/src/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts index c3fa141f65c..2f4f6bed288 100644 --- a/src/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts @@ -23,7 +23,7 @@ import { Command } from "#app/ui/command-ui-handler"; import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils"; const namespace = "mysteryEncounters/funAndGames"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -45,10 +45,10 @@ describe("Fun And Games! - Mystery Encounter", () => { game.override.disableTrainerWaves(); const biomeMap = new Map([ - [Biome.VOLCANO, [MysteryEncounterType.FIGHT_OR_FLIGHT]], + [ Biome.VOLCANO, [ MysteryEncounterType.FIGHT_OR_FLIGHT ]], ]); HUMAN_TRANSITABLE_BIOMES.forEach(biome => { - biomeMap.set(biome, [MysteryEncounterType.FUN_AND_GAMES]); + biomeMap.set(biome, [ MysteryEncounterType.FUN_AND_GAMES ]); }); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap); }); @@ -137,13 +137,13 @@ describe("Fun And Games! - Mystery Encounter", () => { it("should get 3 turns to attack the Wobbuffet for a reward", async () => { scene.money = 20000; - game.override.moveset([Moves.TACKLE]); + game.override.moveset([ Moves.TACKLE ]); await game.runToMysteryEncounter(MysteryEncounterType.FUN_AND_GAMES, defaultParty); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1 }, true); expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(scene.getEnemyPokemon()?.species.speciesId).toBe(Species.WOBBUFFET); - expect(scene.getEnemyPokemon()?.ivs).toEqual([0, 0, 0, 0, 0, 0]); + expect(scene.getEnemyPokemon()?.ivs).toEqual([ 0, 0, 0, 0, 0, 0 ]); expect(scene.getEnemyPokemon()?.nature).toBe(Nature.MILD); game.onNextPrompt("MessagePhase", Mode.MESSAGE, () => { @@ -192,7 +192,7 @@ describe("Fun And Games! - Mystery Encounter", () => { it("should have Wide Lens item in rewards if Wubboffet is at 15-33% HP remaining", async () => { scene.money = 20000; - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); await game.runToMysteryEncounter(MysteryEncounterType.FUN_AND_GAMES, defaultParty); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1 }, true); @@ -220,7 +220,7 @@ describe("Fun And Games! - Mystery Encounter", () => { it("should have Scope Lens item in rewards if Wubboffet is at 3-15% HP remaining", async () => { scene.money = 20000; - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); await game.runToMysteryEncounter(MysteryEncounterType.FUN_AND_GAMES, defaultParty); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1 }, true); @@ -248,7 +248,7 @@ describe("Fun And Games! - Mystery Encounter", () => { it("should have Multi Lens item in rewards if Wubboffet is at <3% HP remaining", async () => { scene.money = 20000; - game.override.moveset([Moves.SPLASH]); + game.override.moveset([ Moves.SPLASH ]); await game.runToMysteryEncounter(MysteryEncounterType.FUN_AND_GAMES, defaultParty); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1 }, true); diff --git a/src/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts b/src/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts index 17f6a74e480..b08f8008b68 100644 --- a/src/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts @@ -20,7 +20,7 @@ import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; import { ModifierTier } from "#app/modifier/modifier-tier"; const namespace = "mysteryEncounters/globalTradeSystem"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -42,10 +42,10 @@ describe("Global Trade System - Mystery Encounter", () => { game.override.disableTrainerWaves(); const biomeMap = new Map([ - [Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.VOLCANO, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]); CIVILIZATION_ENCOUNTER_BIOMES.forEach(biome => { - biomeMap.set(biome, [MysteryEncounterType.GLOBAL_TRADE_SYSTEM]); + biomeMap.set(biome, [ MysteryEncounterType.GLOBAL_TRADE_SYSTEM ]); }); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap); }); @@ -70,7 +70,7 @@ describe("Global Trade System - Mystery Encounter", () => { }); it("should not loop infinitely when generating trade options for extreme BST non-legendaries", async () => { - const extremeBstTeam = [Species.SLAKING, Species.WISHIWASHI, Species.SUNKERN]; + const extremeBstTeam = [ Species.SLAKING, Species.WISHIWASHI, Species.SUNKERN ]; await game.runToMysteryEncounter(MysteryEncounterType.GLOBAL_TRADE_SYSTEM, extremeBstTeam); expect(GlobalTradeSystemEncounter.encounterType).toBe(MysteryEncounterType.GLOBAL_TRADE_SYSTEM); @@ -209,7 +209,7 @@ describe("Global Trade System - Mystery Encounter", () => { await scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); expect(scene.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); await game.phaseInterceptor.run(SelectModifierPhase); @@ -234,7 +234,7 @@ describe("Global Trade System - Mystery Encounter", () => { await scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); - await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1}); + await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); expect(leaveEncounterWithoutBattleSpy).toBeCalled(); }); diff --git a/src/test/mystery-encounter/encounters/lost-at-sea-encounter.test.ts b/src/test/mystery-encounter/encounters/lost-at-sea-encounter.test.ts index bb7a74d6fd0..dec14d46cc8 100644 --- a/src/test/mystery-encounter/encounters/lost-at-sea-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/lost-at-sea-encounter.test.ts @@ -14,11 +14,12 @@ import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; import BattleScene from "#app/battle-scene"; import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; import { PartyExpPhase } from "#app/phases/party-exp-phase"; +import i18next from "i18next"; const namespace = "mysteryEncounters/lostAtSea"; /** Blastoise for surf. Pidgeot for fly. Abra for none. */ -const defaultParty = [Species.BLASTOISE, Species.PIDGEOT, Species.ABRA]; +const defaultParty = [ Species.BLASTOISE, Species.PIDGEOT, Species.ABRA ]; const defaultBiome = Biome.SEA; const defaultWave = 33; @@ -41,8 +42,8 @@ describe("Lost at Sea - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.SEA, [MysteryEncounterType.LOST_AT_SEA]], - [Biome.MOUNTAIN, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.SEA, [ MysteryEncounterType.LOST_AT_SEA ]], + [ Biome.MOUNTAIN, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]) ); }); @@ -86,8 +87,8 @@ describe("Lost at Sea - Mystery Encounter", () => { const onInitResult = onInit!(scene); expect(LostAtSeaEncounter.dialogueTokens?.damagePercentage).toBe("25"); - expect(LostAtSeaEncounter.dialogueTokens?.option1RequiredMove).toBe("move:surf.name"); - expect(LostAtSeaEncounter.dialogueTokens?.option2RequiredMove).toBe("move:fly.name"); + expect(LostAtSeaEncounter.dialogueTokens?.option1RequiredMove).toBe(i18next.t("move:surf.name")); + expect(LostAtSeaEncounter.dialogueTokens?.option2RequiredMove).toBe(i18next.t("move:fly.name")); expect(onInitResult).toBe(true); }); @@ -134,7 +135,7 @@ describe("Lost at Sea - Mystery Encounter", () => { }); it("should be disabled if no surfable PKM is in party", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, [Species.ARCANINE]); + await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, [ Species.ARCANINE ]); await game.phaseInterceptor.to(MysteryEncounterPhase, false); const encounterPhase = scene.getCurrentPhase(); @@ -199,7 +200,7 @@ describe("Lost at Sea - Mystery Encounter", () => { }); it("should be disabled if no flyable PKM is in party", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, [Species.ARCANINE]); + await game.runToMysteryEncounter(MysteryEncounterType.LOST_AT_SEA, [ Species.ARCANINE ]); await game.phaseInterceptor.to(MysteryEncounterPhase, false); const encounterPhase = scene.getCurrentPhase(); diff --git a/src/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts b/src/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts index b8df60b60ec..7bbc505dd8e 100644 --- a/src/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts @@ -22,7 +22,7 @@ import { CommandPhase } from "#app/phases/command-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; const namespace = "mysteryEncounters/mysteriousChallengers"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -44,10 +44,10 @@ describe("Mysterious Challengers - Mystery Encounter", () => { game.override.disableTrainerWaves(); const biomeMap = new Map([ - [Biome.VOLCANO, [MysteryEncounterType.FIGHT_OR_FLIGHT]], + [ Biome.VOLCANO, [ MysteryEncounterType.FIGHT_OR_FLIGHT ]], ]); HUMAN_TRANSITABLE_BIOMES.forEach(biome => { - biomeMap.set(biome, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]); + biomeMap.set(biome, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]); }); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap); }); diff --git a/src/test/mystery-encounter/encounters/part-timer-encounter.test.ts b/src/test/mystery-encounter/encounters/part-timer-encounter.test.ts index e359c4fd575..ba8ce648a3f 100644 --- a/src/test/mystery-encounter/encounters/part-timer-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/part-timer-encounter.test.ts @@ -17,7 +17,7 @@ import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; const namespace = "mysteryEncounters/partTimer"; // Pyukumuku for lowest speed, Regieleki for highest speed, Feebas for lowest "bulk", Melmetal for highest "bulk" -const defaultParty = [Species.PYUKUMUKU, Species.REGIELEKI, Species.FEEBAS, Species.MELMETAL]; +const defaultParty = [ Species.PYUKUMUKU, Species.REGIELEKI, Species.FEEBAS, Species.MELMETAL ]; const defaultBiome = Biome.PLAINS; const defaultWave = 37; @@ -39,10 +39,10 @@ describe("Part-Timer - Mystery Encounter", () => { game.override.disableTrainerWaves(); const biomeMap = new Map([ - [Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.VOLCANO, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]); CIVILIZATION_ENCOUNTER_BIOMES.forEach(biome => { - biomeMap.set(biome, [MysteryEncounterType.PART_TIMER]); + biomeMap.set(biome, [ MysteryEncounterType.PART_TIMER ]); }); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap); }); @@ -122,7 +122,7 @@ describe("Part-Timer - Mystery Encounter", () => { // Override party levels to 50 so stats can be fully reflective scene.getParty().forEach(p => { p.level = 50; - p.ivs = [20, 20, 20, 20, 20, 20]; + p.ivs = [ 20, 20, 20, 20, 20, 20 ]; p.calculateStats(); }); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 2 }); @@ -187,7 +187,7 @@ describe("Part-Timer - Mystery Encounter", () => { // Override party levels to 50 so stats can be fully reflective scene.getParty().forEach(p => { p.level = 50; - p.ivs = [20, 20, 20, 20, 20, 20]; + p.ivs = [ 20, 20, 20, 20, 20, 20 ]; p.calculateStats(); }); await runMysteryEncounterToEnd(game, 2, { pokemonNo: 4 }); @@ -256,7 +256,7 @@ describe("Part-Timer - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.PART_TIMER, defaultParty); // Mock moveset - scene.getParty()[0].moveset = [new PokemonMove(Moves.ATTRACT)]; + scene.getParty()[0].moveset = [ new PokemonMove(Moves.ATTRACT) ]; await runMysteryEncounterToEnd(game, 3); expect(EncounterPhaseUtils.updatePlayerMoney).toHaveBeenCalledWith(scene, scene.getWaveMoneyAmount(2.5), true, false); diff --git a/src/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts b/src/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts index b12452f0a77..02375d83b98 100644 --- a/src/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts @@ -1,28 +1,29 @@ -import * as MysteryEncounters from "#app/data/mystery-encounters/mystery-encounters"; -import { Biome } from "#app/enums/biome"; -import { MysteryEncounterType } from "#app/enums/mystery-encounter-type"; -import { Species } from "#app/enums/species"; -import GameManager from "#app/test/utils/gameManager"; -import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils"; import BattleScene from "#app/battle-scene"; +import { TeleportingHijinksEncounter } from "#app/data/mystery-encounters/encounters/teleporting-hijinks-encounter"; +import * as MysteryEncounters from "#app/data/mystery-encounters/mystery-encounters"; +import { Abilities } from "#enums/abilities"; +import { Biome } from "#enums/biome"; +import { MysteryEncounterType } from "#enums/mystery-encounter-type"; +import { Species } from "#enums/species"; +import { CommandPhase } from "#app/phases/command-phase"; +import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; +import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; +import GameManager from "#test/utils/gameManager"; +import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; +import { Mode } from "#app/ui/ui"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; +import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, skipBattleRunMysteryEncounterRewardsPhase } from "#test/mystery-encounter/encounter-test-utils"; import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; -import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; -import { CommandPhase } from "#app/phases/command-phase"; -import { TeleportingHijinksEncounter } from "#app/data/mystery-encounters/encounters/teleporting-hijinks-encounter"; -import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; -import { Mode } from "#app/ui/ui"; -import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; -import { Abilities } from "#app/enums/abilities"; +import i18next from "i18next"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; const namespace = "mysteryEncounters/teleportingHijinks"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; -const TRANSPORT_BIOMES = [Biome.SPACE, Biome.ISLAND, Biome.LABORATORY, Biome.FAIRY_CAVE, Biome.WASTELAND, Biome.DOJO]; +const TRANSPORT_BIOMES = [ Biome.SPACE, Biome.ISLAND, Biome.LABORATORY, Biome.FAIRY_CAVE, Biome.WASTELAND, Biome.DOJO ]; describe("Teleporting Hijinks - Mystery Encounter", () => { let phaserGame: Phaser.Game; @@ -47,7 +48,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.TELEPORTING_HIJINKS]], + [ Biome.CAVE, [ MysteryEncounterType.TELEPORTING_HIJINKS ]], ]) ); }); @@ -180,7 +181,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty); await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(enemyField[0].summonData.statStages).toEqual([0, 1, 0, 1, 1, 0, 0]); + expect(enemyField[0].summonData.statStages).toEqual([ 0, 1, 0, 1, 1, 0, 0 ]); expect(enemyField[0].isBoss()).toBe(true); }); @@ -189,7 +190,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty); await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(enemyField[0].summonData.statStages).toEqual([1, 1, 1, 1, 1, 0, 0]); + expect(enemyField[0].summonData.statStages).toEqual([ 1, 1, 1, 1, 1, 0, 0 ]); expect(enemyField[0].isBoss()).toBe(true); }); }); @@ -212,7 +213,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { }); it("should NOT be selectable if the player doesn't the right type pokemon", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [Species.BLASTOISE]); + await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [ Species.BLASTOISE ]); await game.phaseInterceptor.to(MysteryEncounterPhase, false); const encounterPhase = scene.getCurrentPhase(); @@ -231,14 +232,14 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { }); it("should be selectable if the player has the right type pokemon", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [Species.METAGROSS]); + await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [ Species.METAGROSS ]); await runMysteryEncounterToEnd(game, 2, undefined, true); expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); }); it("should transport to a new area", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [Species.PIKACHU]); + await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [ Species.PIKACHU ]); const previousBiome = scene.arena.biomeType; @@ -249,19 +250,19 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { }); it("should start a battle against an enraged boss below wave 50", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [Species.PIKACHU]); + await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [ Species.PIKACHU ]); await runMysteryEncounterToEnd(game, 2, undefined, true); const enemyField = scene.getEnemyField(); - expect(enemyField[0].summonData.statStages).toEqual([0, 1, 0, 1, 1, 0, 0]); + expect(enemyField[0].summonData.statStages).toEqual([ 0, 1, 0, 1, 1, 0, 0 ]); expect(enemyField[0].isBoss()).toBe(true); }); it("should start a battle against an extra enraged boss above wave 50", { retry: 5 }, async () => { game.override.startingWave(56); - await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [Species.PIKACHU]); + await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [ Species.PIKACHU ]); await runMysteryEncounterToEnd(game, 2, undefined, true); const enemyField = scene.getEnemyField(); - expect(enemyField[0].summonData.statStages).toEqual([1, 1, 1, 1, 1, 0, 0]); + expect(enemyField[0].summonData.statStages).toEqual([ 1, 1, 1, 1, 1, 0, 0 ]); expect(enemyField[0].isBoss()).toBe(true); }); }); @@ -286,7 +287,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty); await runMysteryEncounterToEnd(game, 3, undefined, true); const enemyField = scene.getEnemyField(); - expect(enemyField[0].summonData.statStages).toEqual([0, 0, 0, 0, 0, 0, 0]); + expect(enemyField[0].summonData.statStages).toEqual([ 0, 0, 0, 0, 0, 0, 0 ]); expect(enemyField[0].isBoss()).toBe(true); }); @@ -300,8 +301,8 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { expect(scene.ui.getMode()).to.equal(Mode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find(h => h instanceof ModifierSelectUiHandler) as ModifierSelectUiHandler; - expect(modifierSelectHandler.options.some(opt => opt.modifierTypeOption.type.name === "modifierType:AttackTypeBoosterItem.metal_coat")).toBe(true); - expect(modifierSelectHandler.options.some(opt => opt.modifierTypeOption.type.name === "modifierType:AttackTypeBoosterItem.magnet")).toBe(true); + expect(modifierSelectHandler.options.some(opt => opt.modifierTypeOption.type.name === i18next.t("modifierType:AttackTypeBoosterItem.metal_coat"))).toBe(true); + expect(modifierSelectHandler.options.some(opt => opt.modifierTypeOption.type.name === i18next.t("modifierType:AttackTypeBoosterItem.magnet"))).toBe(true); }); }); }); diff --git a/src/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts b/src/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts index a0120522fd2..a3a43815ec6 100644 --- a/src/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts @@ -20,7 +20,7 @@ import { EggTier } from "#enums/egg-type"; import { PostMysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; const namespace = "mysteryEncounters/theExpertPokemonBreeder"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -42,10 +42,10 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { game.override.disableTrainerWaves(); const biomeMap = new Map([ - [Biome.VOLCANO, [MysteryEncounterType.FIGHT_OR_FLIGHT]], + [ Biome.VOLCANO, [ MysteryEncounterType.FIGHT_OR_FLIGHT ]], ]); HUMAN_TRANSITABLE_BIOMES.forEach(biome => { - biomeMap.set(biome, [MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER]); + biomeMap.set(biome, [ MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER ]); }); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap); }); @@ -124,10 +124,31 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { }); }); - it("should start battle against the trainer", async () => { + it("should start battle against the trainer with correctly loaded assets", async () => { await game.runToMysteryEncounter(MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER, defaultParty); + + let successfullyLoaded = false; + vi.spyOn(scene, "getEnemyParty").mockImplementation(() => { + const ace = scene.currentBattle?.enemyParty[0]; + if (ace) { + // Pretend that loading assets takes an extra 500ms + vi.spyOn(ace, "loadAssets").mockImplementation(() => new Promise(resolve => { + setTimeout(() => { + successfullyLoaded = true; + resolve(); + }, 500); + })); + } + + return scene.currentBattle?.enemyParty ?? []; + }); + await runMysteryEncounterToEnd(game, 1, undefined, true); + // Check that assets are successfully loaded + expect(successfullyLoaded).toBe(true); + + // Check usual battle stuff expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(scene.currentBattle.trainer).toBeDefined(); expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE); @@ -155,7 +176,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { expect(eggsAfter).toBeDefined(); expect(eggsBeforeLength + commonEggs + rareEggs).toBe(eggsAfter.length); expect(eggsAfter.filter(egg => egg.tier === EggTier.COMMON).length).toBe(commonEggs); - expect(eggsAfter.filter(egg => egg.tier === EggTier.GREAT).length).toBe(rareEggs); + expect(eggsAfter.filter(egg => egg.tier === EggTier.RARE).length).toBe(rareEggs); game.phaseInterceptor.superEndPhase(); await game.phaseInterceptor.to(PostMysteryEncounterPhase); @@ -182,10 +203,31 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { }); }); - it("should start battle against the trainer", async () => { + it("should start battle against the trainer with correctly loaded assets", async () => { await game.runToMysteryEncounter(MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER, defaultParty); + + let successfullyLoaded = false; + vi.spyOn(scene, "getEnemyParty").mockImplementation(() => { + const ace = scene.currentBattle?.enemyParty[0]; + if (ace) { + // Pretend that loading assets takes an extra 500ms + vi.spyOn(ace, "loadAssets").mockImplementation(() => new Promise(resolve => { + setTimeout(() => { + successfullyLoaded = true; + resolve(); + }, 500); + })); + } + + return scene.currentBattle?.enemyParty ?? []; + }); + await runMysteryEncounterToEnd(game, 2, undefined, true); + // Check that assets are successfully loaded + expect(successfullyLoaded).toBe(true); + + // Check usual battle stuff expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(scene.currentBattle.trainer).toBeDefined(); expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE); @@ -213,7 +255,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { expect(eggsAfter).toBeDefined(); expect(eggsBeforeLength + commonEggs + rareEggs).toBe(eggsAfter.length); expect(eggsAfter.filter(egg => egg.tier === EggTier.COMMON).length).toBe(commonEggs); - expect(eggsAfter.filter(egg => egg.tier === EggTier.GREAT).length).toBe(rareEggs); + expect(eggsAfter.filter(egg => egg.tier === EggTier.RARE).length).toBe(rareEggs); game.phaseInterceptor.superEndPhase(); await game.phaseInterceptor.to(PostMysteryEncounterPhase); @@ -240,10 +282,31 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { }); }); - it("should start battle against the trainer", async () => { + it("should start battle against the trainer with correctly loaded assets", async () => { await game.runToMysteryEncounter(MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER, defaultParty); + + let successfullyLoaded = false; + vi.spyOn(scene, "getEnemyParty").mockImplementation(() => { + const ace = scene.currentBattle?.enemyParty[0]; + if (ace) { + // Pretend that loading assets takes an extra 500ms + vi.spyOn(ace, "loadAssets").mockImplementation(() => new Promise(resolve => { + setTimeout(() => { + successfullyLoaded = true; + resolve(); + }, 500); + })); + } + + return scene.currentBattle?.enemyParty ?? []; + }); + await runMysteryEncounterToEnd(game, 3, undefined, true); + // Check that assets are successfully loaded + expect(successfullyLoaded).toBe(true); + + // Check usual battle stuff expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(scene.currentBattle.trainer).toBeDefined(); expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE); @@ -271,7 +334,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { expect(eggsAfter).toBeDefined(); expect(eggsBeforeLength + commonEggs + rareEggs).toBe(eggsAfter.length); expect(eggsAfter.filter(egg => egg.tier === EggTier.COMMON).length).toBe(commonEggs); - expect(eggsAfter.filter(egg => egg.tier === EggTier.GREAT).length).toBe(rareEggs); + expect(eggsAfter.filter(egg => egg.tier === EggTier.RARE).length).toBe(rareEggs); game.phaseInterceptor.superEndPhase(); await game.phaseInterceptor.to(PostMysteryEncounterPhase); diff --git a/src/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts b/src/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts index 24994b61b83..040381c4ac3 100644 --- a/src/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts @@ -16,7 +16,7 @@ import { initSceneWithoutEncounterPhase } from "#test/utils/gameManagerUtils"; import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; const namespace = "mysteryEncounters/thePokemonSalesman"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -38,10 +38,10 @@ describe("The Pokemon Salesman - Mystery Encounter", () => { game.override.disableTrainerWaves(); const biomeMap = new Map([ - [Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.VOLCANO, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]); HUMAN_TRANSITABLE_BIOMES.forEach(biome => { - biomeMap.set(biome, [MysteryEncounterType.THE_POKEMON_SALESMAN]); + biomeMap.set(biome, [ MysteryEncounterType.THE_POKEMON_SALESMAN ]); }); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap); }); @@ -147,8 +147,8 @@ describe("The Pokemon Salesman - Mystery Encounter", () => { expect(scene.getParty().length).toBe(initialPartySize + 1); - const newlyPurchasedPokemon = scene.getParty().find(p => p.name === pokemonName); - expect(newlyPurchasedPokemon).toBeDefined(); + const newlyPurchasedPokemon = scene.getParty()[scene.getParty().length - 1]; + expect(newlyPurchasedPokemon.name).toBe(pokemonName); expect(newlyPurchasedPokemon!.moveset.length > 0).toBeTruthy(); }); diff --git a/src/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts b/src/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts index 927e5cf0b02..04a125fb7ad 100644 --- a/src/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts @@ -28,7 +28,7 @@ import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { Abilities } from "#app/enums/abilities"; const namespace = "mysteryEncounters/theStrongStuff"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -54,8 +54,8 @@ describe("The Strong Stuff - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.THE_STRONG_STUFF]], - [Biome.MOUNTAIN, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]], + [ Biome.CAVE, [ MysteryEncounterType.THE_STRONG_STUFF ]], + [ Biome.MOUNTAIN, [ MysteryEncounterType.MYSTERIOUS_CHALLENGERS ]], ]) ); }); @@ -111,9 +111,9 @@ describe("The Strong Stuff - Mystery Encounter", () => { bossSegments: 5, mysteryEncounterPokemonData: new CustomPokemonData({ spriteScale: 1.25 }), nature: Nature.BOLD, - moveSet: [Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER], + moveSet: [ Moves.INFESTATION, Moves.SALT_CURE, Moves.GASTRO_ACID, Moves.HEAL_ORDER ], modifierConfigs: expect.any(Array), - tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], + tags: [ BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON ], mysteryEncounterBattleEffects: expect.any(Function) } ], @@ -194,7 +194,7 @@ describe("The Strong Stuff - Mystery Encounter", () => { expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(Species.SHUCKLE); - expect(enemyField[0].summonData.statStages).toEqual([0, 2, 0, 2, 0, 0, 0]); + expect(enemyField[0].summonData.statStages).toEqual([ 0, 2, 0, 2, 0, 0, 0 ]); const shuckleItems = enemyField[0].getHeldItems(); expect(shuckleItems.length).toBe(5); expect(shuckleItems.find(m => m instanceof BerryModifier && m.berryType === BerryType.SITRUS)?.stackCount).toBe(1); @@ -202,7 +202,7 @@ describe("The Strong Stuff - Mystery Encounter", () => { expect(shuckleItems.find(m => m instanceof BerryModifier && m.berryType === BerryType.GANLON)?.stackCount).toBe(1); expect(shuckleItems.find(m => m instanceof BerryModifier && m.berryType === BerryType.APICOT)?.stackCount).toBe(1); expect(shuckleItems.find(m => m instanceof BerryModifier && m.berryType === BerryType.LUM)?.stackCount).toBe(2); - expect(enemyField[0].moveset).toEqual([new PokemonMove(Moves.INFESTATION), new PokemonMove(Moves.SALT_CURE), new PokemonMove(Moves.GASTRO_ACID), new PokemonMove(Moves.HEAL_ORDER)]); + expect(enemyField[0].moveset).toEqual([ new PokemonMove(Moves.INFESTATION), new PokemonMove(Moves.SALT_CURE), new PokemonMove(Moves.GASTRO_ACID), new PokemonMove(Moves.HEAL_ORDER) ]); // Should have used moves pre-battle const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]); diff --git a/src/test/mystery-encounter/encounters/the-winstrate-challenge-encounter.test.ts b/src/test/mystery-encounter/encounters/the-winstrate-challenge-encounter.test.ts index 93f01200203..2653b76ab7c 100644 --- a/src/test/mystery-encounter/encounters/the-winstrate-challenge-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/the-winstrate-challenge-encounter.test.ts @@ -27,7 +27,7 @@ import { PartyHealPhase } from "#app/phases/party-heal-phase"; import { VictoryPhase } from "#app/phases/victory-phase"; const namespace = "mysteryEncounters/theWinstrateChallenge"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -49,10 +49,10 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { game.override.disableTrainerWaves(); const biomeMap = new Map([ - [Biome.VOLCANO, [MysteryEncounterType.FIGHT_OR_FLIGHT]], + [ Biome.VOLCANO, [ MysteryEncounterType.FIGHT_OR_FLIGHT ]], ]); HUMAN_TRANSITABLE_BIOMES.forEach(biome => { - biomeMap.set(biome, [MysteryEncounterType.THE_WINSTRATE_CHALLENGE]); + biomeMap.set(biome, [ MysteryEncounterType.THE_WINSTRATE_CHALLENGE ]); }); vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap); }); @@ -114,7 +114,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, abilityIndex: 0, // Soundproof nature: Nature.MODEST, - moveSet: [Moves.THUNDERBOLT, Moves.GIGA_DRAIN, Moves.FOUL_PLAY, Moves.THUNDER_WAVE], + moveSet: [ Moves.THUNDERBOLT, Moves.GIGA_DRAIN, Moves.FOUL_PLAY, Moves.THUNDER_WAVE ], modifierConfigs: expect.any(Array) }, { @@ -122,7 +122,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, abilityIndex: 2, // Gluttony nature: Nature.QUIET, - moveSet: [Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.ICE_BEAM, Moves.EARTHQUAKE], + moveSet: [ Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.ICE_BEAM, Moves.EARTHQUAKE ], modifierConfigs: expect.any(Array) }, { @@ -130,7 +130,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, abilityIndex: 2, // Tangled Feet nature: Nature.JOLLY, - moveSet: [Moves.DRILL_PECK, Moves.QUICK_ATTACK, Moves.THRASH, Moves.KNOCK_OFF], + moveSet: [ Moves.DRILL_PECK, Moves.QUICK_ATTACK, Moves.THRASH, Moves.KNOCK_OFF ], modifierConfigs: expect.any(Array) }, { @@ -138,7 +138,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, formIndex: 1, nature: Nature.BOLD, - moveSet: [Moves.PSYCHIC, Moves.SHADOW_BALL, Moves.FOCUS_BLAST, Moves.THUNDERBOLT], + moveSet: [ Moves.PSYCHIC, Moves.SHADOW_BALL, Moves.FOCUS_BLAST, Moves.THUNDERBOLT ], modifierConfigs: expect.any(Array) }, { @@ -146,7 +146,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, abilityIndex: 0, // Sheer Force nature: Nature.IMPISH, - moveSet: [Moves.EARTHQUAKE, Moves.U_TURN, Moves.FLARE_BLITZ, Moves.ROCK_SLIDE], + moveSet: [ Moves.EARTHQUAKE, Moves.U_TURN, Moves.FLARE_BLITZ, Moves.ROCK_SLIDE ], modifierConfigs: expect.any(Array) } ] @@ -159,7 +159,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, formIndex: 1, nature: Nature.IMPISH, - moveSet: [Moves.AXE_KICK, Moves.ICE_PUNCH, Moves.ZEN_HEADBUTT, Moves.BULLET_PUNCH], + moveSet: [ Moves.AXE_KICK, Moves.ICE_PUNCH, Moves.ZEN_HEADBUTT, Moves.BULLET_PUNCH ], modifierConfigs: expect.any(Array) } ] @@ -172,7 +172,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, abilityIndex: 3, // Lightning Rod nature: Nature.ADAMANT, - moveSet: [Moves.WATERFALL, Moves.MEGAHORN, Moves.KNOCK_OFF, Moves.REST], + moveSet: [ Moves.WATERFALL, Moves.MEGAHORN, Moves.KNOCK_OFF, Moves.REST ], modifierConfigs: expect.any(Array) }, { @@ -180,7 +180,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, abilityIndex: 1, // Poison Heal nature: Nature.JOLLY, - moveSet: [Moves.SPORE, Moves.SWORDS_DANCE, Moves.SEED_BOMB, Moves.DRAIN_PUNCH], + moveSet: [ Moves.SPORE, Moves.SWORDS_DANCE, Moves.SEED_BOMB, Moves.DRAIN_PUNCH ], modifierConfigs: expect.any(Array) }, { @@ -188,7 +188,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, formIndex: 1, nature: Nature.CALM, - moveSet: [Moves.EARTH_POWER, Moves.FIRE_BLAST, Moves.YAWN, Moves.PROTECT], + moveSet: [ Moves.EARTH_POWER, Moves.FIRE_BLAST, Moves.YAWN, Moves.PROTECT ], modifierConfigs: expect.any(Array) } ] @@ -201,7 +201,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, abilityIndex: 0, // Natural Cure nature: Nature.CALM, - moveSet: [Moves.SYNTHESIS, Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.SLEEP_POWDER], + moveSet: [ Moves.SYNTHESIS, Moves.SLUDGE_BOMB, Moves.GIGA_DRAIN, Moves.SLEEP_POWDER ], modifierConfigs: expect.any(Array) }, { @@ -209,7 +209,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, formIndex: 1, nature: Nature.TIMID, - moveSet: [Moves.PSYSHOCK, Moves.MOONBLAST, Moves.SHADOW_BALL, Moves.WILL_O_WISP], + moveSet: [ Moves.PSYSHOCK, Moves.MOONBLAST, Moves.SHADOW_BALL, Moves.WILL_O_WISP ], modifierConfigs: expect.any(Array) } ] @@ -222,7 +222,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, abilityIndex: 0, // Guts nature: Nature.ADAMANT, - moveSet: [Moves.FACADE, Moves.BRAVE_BIRD, Moves.PROTECT, Moves.QUICK_ATTACK], + moveSet: [ Moves.FACADE, Moves.BRAVE_BIRD, Moves.PROTECT, Moves.QUICK_ATTACK ], modifierConfigs: expect.any(Array) }, { @@ -230,7 +230,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { isBoss: false, abilityIndex: 1, // Guts nature: Nature.ADAMANT, - moveSet: [Moves.FACADE, Moves.OBSTRUCT, Moves.NIGHT_SLASH, Moves.FIRE_PUNCH], + moveSet: [ Moves.FACADE, Moves.OBSTRUCT, Moves.NIGHT_SLASH, Moves.FIRE_PUNCH ], modifierConfigs: expect.any(Array) } ] diff --git a/src/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts b/src/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts index 9120632f9e2..8286c6a694b 100644 --- a/src/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts @@ -24,7 +24,7 @@ import { CommandPhase } from "#app/phases/command-phase"; import { MovePhase } from "#app/phases/move-phase"; const namespace = "mysteryEncounters/trashToTreasure"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -47,7 +47,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.TRASH_TO_TREASURE]], + [ Biome.CAVE, [ MysteryEncounterType.TRASH_TO_TREASURE ]], ]) ); }); @@ -94,7 +94,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { isBoss: true, formIndex: 1, bossSegmentModifier: 1, - moveSet: [Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH], + moveSet: [ Moves.PAYBACK, Moves.GUNK_SHOT, Moves.STOMPING_TANTRUM, Moves.DRAIN_PUNCH ], } ], } @@ -175,7 +175,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { expect(scene.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(Species.GARBODOR); - expect(enemyField[0].moveset).toEqual([new PokemonMove(Moves.PAYBACK), new PokemonMove(Moves.GUNK_SHOT), new PokemonMove(Moves.STOMPING_TANTRUM), new PokemonMove(Moves.DRAIN_PUNCH)]); + expect(enemyField[0].moveset).toEqual([ new PokemonMove(Moves.PAYBACK), new PokemonMove(Moves.GUNK_SHOT), new PokemonMove(Moves.STOMPING_TANTRUM), new PokemonMove(Moves.DRAIN_PUNCH) ]); // Should have used moves pre-battle const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]); diff --git a/src/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts b/src/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts index fa3c97b56ce..fa1b5ecdeb7 100644 --- a/src/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts @@ -27,7 +27,7 @@ import { modifierTypes } from "#app/modifier/modifier-type"; import { Abilities } from "#enums/abilities"; const namespace = "mysteryEncounters/uncommonBreed"; -const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA]; +const defaultParty = [ Species.LAPRAS, Species.GENGAR, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -53,7 +53,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.UNCOMMON_BREED]], + [ Biome.CAVE, [ MysteryEncounterType.UNCOMMON_BREED ]], ]) ); }); @@ -126,7 +126,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); const statStagePhases = unshiftPhaseSpy.mock.calls.filter(p => p[0] instanceof StatStageChangePhase)[0][0] as any; - expect(statStagePhases.stats).toEqual([Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD]); + expect(statStagePhases.stats).toEqual([ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ]); // Should have used its egg move pre-battle const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]); @@ -153,7 +153,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); const statStagePhases = unshiftPhaseSpy.mock.calls.filter(p => p[0] instanceof StatStageChangePhase)[0][0] as any; - expect(statStagePhases.stats).toEqual([Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD]); + expect(statStagePhases.stats).toEqual([ Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD ]); // Should have used its egg move pre-battle const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]); @@ -213,11 +213,11 @@ describe("Uncommon Breed - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.UNCOMMON_BREED, defaultParty); // Berries on party lead - const sitrus = generateModifierType(scene, modifierTypes.BERRY, [BerryType.SITRUS])!; + const sitrus = generateModifierType(scene, modifierTypes.BERRY, [ BerryType.SITRUS ])!; const sitrusMod = sitrus.newModifier(scene.getParty()[0]) as BerryModifier; sitrusMod.stackCount = 2; await scene.addModifier(sitrusMod, true, false, false, true); - const ganlon = generateModifierType(scene, modifierTypes.BERRY, [BerryType.GANLON])!; + const ganlon = generateModifierType(scene, modifierTypes.BERRY, [ BerryType.GANLON ])!; const ganlonMod = ganlon.newModifier(scene.getParty()[0]) as BerryModifier; ganlonMod.stackCount = 3; await scene.addModifier(ganlonMod, true, false, false, true); @@ -270,7 +270,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); await game.runToMysteryEncounter(MysteryEncounterType.UNCOMMON_BREED, defaultParty); // Mock moveset - scene.getParty()[0].moveset = [new PokemonMove(Moves.CHARM)]; + scene.getParty()[0].moveset = [ new PokemonMove(Moves.CHARM) ]; await runMysteryEncounterToEnd(game, 3); expect(leaveEncounterWithoutBattleSpy).toBeCalled(); diff --git a/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts b/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts index 346e4235e6b..c1fa6d83a18 100644 --- a/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts +++ b/src/test/mystery-encounter/encounters/weird-dream-encounter.test.ts @@ -19,7 +19,7 @@ import { CommandPhase } from "#app/phases/command-phase"; import { ModifierTier } from "#app/modifier/modifier-tier"; const namespace = "mysteryEncounters/weirdDream"; -const defaultParty = [Species.MAGBY, Species.HAUNTER, Species.ABRA]; +const defaultParty = [ Species.MAGBY, Species.HAUNTER, Species.ABRA ]; const defaultBiome = Biome.CAVE; const defaultWave = 45; @@ -43,7 +43,7 @@ describe("Weird Dream - Mystery Encounter", () => { vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue( new Map([ - [Biome.CAVE, [MysteryEncounterType.WEIRD_DREAM]], + [ Biome.CAVE, [ MysteryEncounterType.WEIRD_DREAM ]], ]) ); }); diff --git a/src/test/mystery-encounter/mystery-encounter-utils.test.ts b/src/test/mystery-encounter/mystery-encounter-utils.test.ts index 7541379be07..134966a188d 100644 --- a/src/test/mystery-encounter/mystery-encounter-utils.test.ts +++ b/src/test/mystery-encounter/mystery-encounter-utils.test.ts @@ -31,7 +31,7 @@ describe("Mystery Encounter Utils", () => { beforeEach(() => { game = new GameManager(phaserGame); scene = game.scene; - initSceneWithoutEncounterPhase(game.scene, [Species.ARCEUS, Species.MANAPHY]); + initSceneWithoutEncounterPhase(game.scene, [ Species.ARCEUS, Species.MANAPHY ]); }); describe("getRandomPlayerPokemon", () => { @@ -214,7 +214,7 @@ describe("Mystery Encounter Utils", () => { }); it("gets species for a starter tier range", () => { - const result = getRandomSpeciesByStarterTier([5, 8]); + const result = getRandomSpeciesByStarterTier([ 5, 8 ]); const pokeSpecies = getPokemonSpecies(result); expect(pokeSpecies.speciesId).toBe(result); @@ -224,14 +224,14 @@ describe("Mystery Encounter Utils", () => { it("excludes species from search", () => { // Only 9 tiers are: Koraidon, Miraidon, Arceus, Rayquaza, Kyogre, Groudon, Zacian - const result = getRandomSpeciesByStarterTier(9, [Species.KORAIDON, Species.MIRAIDON, Species.ARCEUS, Species.RAYQUAZA, Species.KYOGRE, Species.GROUDON]); + const result = getRandomSpeciesByStarterTier(9, [ Species.KORAIDON, Species.MIRAIDON, Species.ARCEUS, Species.RAYQUAZA, Species.KYOGRE, Species.GROUDON ]); const pokeSpecies = getPokemonSpecies(result); expect(pokeSpecies.speciesId).toBe(Species.ZACIAN); }); it("gets species of specified types", () => { // Only 9 tiers are: Koraidon, Miraidon, Arceus, Rayquaza, Kyogre, Groudon, Zacian - const result = getRandomSpeciesByStarterTier(9, undefined, [Type.GROUND]); + const result = getRandomSpeciesByStarterTier(9, undefined, [ Type.GROUND ]); const pokeSpecies = getPokemonSpecies(result); expect(pokeSpecies.speciesId).toBe(Species.GROUDON); }); diff --git a/src/test/mystery-encounter/mystery-encounter.test.ts b/src/test/mystery-encounter/mystery-encounter.test.ts index 38c999f8aac..eaf6e04a639 100644 --- a/src/test/mystery-encounter/mystery-encounter.test.ts +++ b/src/test/mystery-encounter/mystery-encounter.test.ts @@ -29,7 +29,7 @@ describe("Mystery Encounters", () => { }); it("Spawns a mystery encounter", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [Species.CHARIZARD, Species.VOLCARONA]); + await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [ Species.CHARIZARD, Species.VOLCARONA ]); await game.phaseInterceptor.to(MysteryEncounterPhase, false); expect(game.scene.getCurrentPhase()!.constructor.name).toBe(MysteryEncounterPhase.name); diff --git a/src/test/phases/learn-move-phase.test.ts b/src/test/phases/learn-move-phase.test.ts index 60cdbee8570..c4fa0e8bf45 100644 --- a/src/test/phases/learn-move-phase.test.ts +++ b/src/test/phases/learn-move-phase.test.ts @@ -25,8 +25,8 @@ describe("Learn Move Phase", () => { }); it("If Pokemon has less than 4 moves, its newest move will be added to the lowest empty index", async () => { - game.override.moveset([Moves.SPLASH]); - await game.startBattle([Species.BULBASAUR]); + game.override.moveset([ Moves.SPLASH ]); + await game.startBattle([ Species.BULBASAUR ]); const pokemon = game.scene.getPlayerPokemon()!; const newMovePos = pokemon?.getMoveset().length; game.move.select(Moves.SPLASH); diff --git a/src/test/phases/mystery-encounter-phase.test.ts b/src/test/phases/mystery-encounter-phase.test.ts index 76b0bd5a905..32e31ce1c94 100644 --- a/src/test/phases/mystery-encounter-phase.test.ts +++ b/src/test/phases/mystery-encounter-phase.test.ts @@ -1,14 +1,15 @@ -import {afterEach, beforeAll, beforeEach, expect, describe, it, vi } from "vitest"; +import { afterEach, beforeAll, beforeEach, expect, describe, it, vi } from "vitest"; import GameManager from "#app/test/utils/gameManager"; import Phaser from "phaser"; -import {Species} from "#enums/species"; +import { Species } from "#enums/species"; import { MysteryEncounterOptionSelectedPhase, MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; -import {Mode} from "#app/ui/ui"; -import {Button} from "#enums/buttons"; +import { Mode } from "#app/ui/ui"; +import { Button } from "#enums/buttons"; import MysteryEncounterUiHandler from "#app/ui/mystery-encounter-ui-handler"; -import {MysteryEncounterType} from "#enums/mystery-encounter-type"; +import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import MessageUiHandler from "#app/ui/message-ui-handler"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; +import i18next from "i18next"; describe("Mystery Encounter Phases", () => { let phaserGame: Phaser.Game; @@ -34,14 +35,14 @@ describe("Mystery Encounter Phases", () => { describe("MysteryEncounterPhase", () => { it("Runs to MysteryEncounterPhase", async() => { - await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [Species.CHARIZARD, Species.VOLCARONA]); + await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [ Species.CHARIZARD, Species.VOLCARONA ]); await game.phaseInterceptor.to(MysteryEncounterPhase, false); expect(game.scene.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); }); it("Runs MysteryEncounterPhase", async() => { - await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [Species.CHARIZARD, Species.VOLCARONA]); + await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [ Species.CHARIZARD, Species.VOLCARONA ]); game.onNextPrompt("MysteryEncounterPhase", Mode.MYSTERY_ENCOUNTER, () => { // End phase early for test @@ -59,7 +60,7 @@ describe("Mystery Encounter Phases", () => { const { ui } = game.scene; vi.spyOn(ui, "showDialogue"); vi.spyOn(ui, "showText"); - await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [Species.CHARIZARD, Species.VOLCARONA]); + await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, [ Species.CHARIZARD, Species.VOLCARONA ]); game.onNextPrompt("MysteryEncounterPhase", Mode.MESSAGE, () => { const handler = game.scene.ui.getHandler() as MessageUiHandler; @@ -78,9 +79,9 @@ describe("Mystery Encounter Phases", () => { expect(ui.getMode()).toBe(Mode.MESSAGE); expect(ui.showDialogue).toHaveBeenCalledTimes(1); expect(ui.showText).toHaveBeenCalledTimes(2); - expect(ui.showDialogue).toHaveBeenCalledWith("battle:mysteryEncounterAppeared", "???", null, expect.any(Function)); - expect(ui.showText).toHaveBeenCalledWith("mysteryEncounters/mysteriousChallengers:intro", null, expect.any(Function), 750, true); - expect(ui.showText).toHaveBeenCalledWith("mysteryEncounters/mysteriousChallengers:option.selected", null, expect.any(Function), 300, true); + expect(ui.showDialogue).toHaveBeenCalledWith(i18next.t("battle:mysteryEncounterAppeared"), "???", null, expect.any(Function)); + expect(ui.showText).toHaveBeenCalledWith(i18next.t("mysteryEncounters/mysteriousChallengers:intro"), null, expect.any(Function), 750, true); + expect(ui.showText).toHaveBeenCalledWith(i18next.t("mysteryEncounters/mysteriousChallengers:option.selected"), null, expect.any(Function), 300, true); }); }); diff --git a/src/test/phases/select-modifier-phase.test.ts b/src/test/phases/select-modifier-phase.test.ts index d946c850ae3..a945aff055b 100644 --- a/src/test/phases/select-modifier-phase.test.ts +++ b/src/test/phases/select-modifier-phase.test.ts @@ -28,7 +28,7 @@ describe("SelectModifierPhase", () => { game = new GameManager(phaserGame); scene = game.scene; - initSceneWithoutEncounterPhase(scene, [Species.ABRA, Species.VOLCARONA]); + initSceneWithoutEncounterPhase(scene, [ Species.ABRA, Species.VOLCARONA ]); }); afterEach(() => { @@ -63,11 +63,11 @@ describe("SelectModifierPhase", () => { new ModifierTypeOption(modifierTypes.REVIVE(), 0, 1000) ]; - const selectModifierPhase1 = new SelectModifierPhase(scene); - const selectModifierPhase2 = new SelectModifierPhase(scene, 0, undefined, { rerollMultiplier: 2 }); + const selectModifierPhase1 = new SelectModifierPhase(scene, 0, undefined, { guaranteedModifierTypeOptions: options }); + const selectModifierPhase2 = new SelectModifierPhase(scene, 0, undefined, { guaranteedModifierTypeOptions: options, rerollMultiplier: 2 }); - const cost1 = selectModifierPhase1.getRerollCost(options, false); - const cost2 = selectModifierPhase2.getRerollCost(options, false); + const cost1 = selectModifierPhase1.getRerollCost(false); + const cost2 = selectModifierPhase2.getRerollCost(false); expect(cost2).toEqual(cost1 * 2); }); @@ -81,7 +81,7 @@ describe("SelectModifierPhase", () => { expect(modifierSelectHandler.options.length).toEqual(3); // Simulate selecting reroll - selectModifierPhase = new SelectModifierPhase(scene, 1, [ModifierTier.COMMON, ModifierTier.COMMON, ModifierTier.COMMON]); + selectModifierPhase = new SelectModifierPhase(scene, 1, [ ModifierTier.COMMON, ModifierTier.COMMON, ModifierTier.COMMON ]); scene.unshiftPhase(selectModifierPhase); scene.ui.setMode(Mode.MESSAGE).then(() => game.endPhase()); await game.phaseInterceptor.run(SelectModifierPhase); @@ -94,7 +94,7 @@ describe("SelectModifierPhase", () => { // Just use fully random seed for this test vi.spyOn(scene, "resetSeed").mockImplementation(() => { scene.waveSeed = Utils.shiftCharCodes(scene.seed, 5); - Phaser.Math.RND.sow([scene.waveSeed]); + Phaser.Math.RND.sow([ scene.waveSeed ]); console.log("Wave Seed:", scene.waveSeed, 5); scene.rngCounter = 0; }); @@ -126,7 +126,7 @@ describe("SelectModifierPhase", () => { it("should generate custom modifiers", async () => { const customModifiers: CustomModifierSettings = { - guaranteedModifierTypeFuncs: [modifierTypes.MEMORY_MUSHROOM, modifierTypes.TM_ULTRA, modifierTypes.LEFTOVERS, modifierTypes.AMULET_COIN, modifierTypes.GOLDEN_PUNCH] + guaranteedModifierTypeFuncs: [ modifierTypes.MEMORY_MUSHROOM, modifierTypes.TM_ULTRA, modifierTypes.LEFTOVERS, modifierTypes.AMULET_COIN, modifierTypes.GOLDEN_PUNCH ] }; const selectModifierPhase = new SelectModifierPhase(scene, 0, undefined, customModifiers); scene.pushPhase(selectModifierPhase); @@ -145,7 +145,7 @@ describe("SelectModifierPhase", () => { it("should generate custom modifier tiers that can upgrade from luck", async () => { const customModifiers: CustomModifierSettings = { - guaranteedModifierTiers: [ModifierTier.COMMON, ModifierTier.GREAT, ModifierTier.ULTRA, ModifierTier.ROGUE, ModifierTier.MASTER] + guaranteedModifierTiers: [ ModifierTier.COMMON, ModifierTier.GREAT, ModifierTier.ULTRA, ModifierTier.ROGUE, ModifierTier.MASTER ] }; const pokemon = new PlayerPokemon(scene, getPokemonSpecies(Species.BULBASAUR), 10, undefined, 0, undefined, true, 2, undefined, undefined, undefined); @@ -172,8 +172,8 @@ describe("SelectModifierPhase", () => { it("should generate custom modifiers and modifier tiers together", async () => { const customModifiers: CustomModifierSettings = { - guaranteedModifierTypeFuncs: [modifierTypes.MEMORY_MUSHROOM, modifierTypes.TM_COMMON], - guaranteedModifierTiers: [ModifierTier.MASTER, ModifierTier.MASTER] + guaranteedModifierTypeFuncs: [ modifierTypes.MEMORY_MUSHROOM, modifierTypes.TM_COMMON ], + guaranteedModifierTiers: [ ModifierTier.MASTER, ModifierTier.MASTER ] }; const selectModifierPhase = new SelectModifierPhase(scene, 0, undefined, customModifiers); scene.pushPhase(selectModifierPhase); @@ -191,8 +191,8 @@ describe("SelectModifierPhase", () => { it("should fill remaining modifiers if fillRemaining is true with custom modifiers", async () => { const customModifiers: CustomModifierSettings = { - guaranteedModifierTypeFuncs: [modifierTypes.MEMORY_MUSHROOM], - guaranteedModifierTiers: [ModifierTier.MASTER], + guaranteedModifierTypeFuncs: [ modifierTypes.MEMORY_MUSHROOM ], + guaranteedModifierTiers: [ ModifierTier.MASTER ], fillRemaining: true }; const selectModifierPhase = new SelectModifierPhase(scene, 0, undefined, customModifiers); diff --git a/src/test/reload.test.ts b/src/test/reload.test.ts index daf8e43a0cd..b15e9691ed6 100644 --- a/src/test/reload.test.ts +++ b/src/test/reload.test.ts @@ -44,15 +44,13 @@ describe("Reload", () => { .startingWave(10) .battleType("single") .startingLevel(100) // Avoid levelling up - .enemyLevel(1000) // Avoid opponent dying before game.doKillOpponents() .disableTrainerWaves() - .moveset([Moves.KOWTOW_CLEAVE]) + .moveset([ Moves.SPLASH ]) .enemyMoveset(Moves.SPLASH); await game.dailyMode.startBattle(); // Transition from Wave 10 to Wave 11 in order to trigger biome switch - game.move.select(Moves.KOWTOW_CLEAVE); - await game.phaseInterceptor.to("DamagePhase"); + game.move.select(Moves.SPLASH); await game.doKillOpponents(); game.onNextPrompt("SelectBiomePhase", Mode.OPTION_SELECT, () => { (game.scene.time as MockClock).overrideDelay = null; @@ -79,15 +77,13 @@ describe("Reload", () => { .startingBiome(Biome.ICE_CAVE) // Will lead to Snowy Forest with randomly generated weather .battleType("single") .startingLevel(100) // Avoid levelling up - .enemyLevel(1000) // Avoid opponent dying before game.doKillOpponents() .disableTrainerWaves() - .moveset([Moves.KOWTOW_CLEAVE]) + .moveset([ Moves.SPLASH ]) .enemyMoveset(Moves.SPLASH); await game.classicMode.startBattle(); // Apparently daily mode would override the biome // Transition from Wave 10 to Wave 11 in order to trigger biome switch - game.move.select(Moves.KOWTOW_CLEAVE); - await game.phaseInterceptor.to("DamagePhase"); + game.move.select(Moves.SPLASH); await game.doKillOpponents(); await game.toNextWave(); expect(game.phaseInterceptor.log).toContain("NewBiomeEncounterPhase"); @@ -161,7 +157,7 @@ describe("Reload", () => { game.override .battleType("single") .startingWave(50); - await game.runToFinalBossEncounter([Species.BULBASAUR], GameModes.DAILY); + await game.runToFinalBossEncounter([ Species.BULBASAUR ], GameModes.DAILY); const preReloadRngState = Phaser.Math.RND.state(); diff --git a/src/test/settingMenu/helpers/menuManip.ts b/src/test/settingMenu/helpers/menuManip.ts index 90b3f1e96e6..0b1f48525f1 100644 --- a/src/test/settingMenu/helpers/menuManip.ts +++ b/src/test/settingMenu/helpers/menuManip.ts @@ -72,7 +72,7 @@ export class MenuManip { const icon = getIconWithKeycode(this.config, this.keycode); const key = getKeyWithKeycode(this.config, this.keycode)!; // TODO: is this bang correct? const _keys = key.toLowerCase().split("_"); - const iconIdentifier = _keys[_keys.length-1]; + const iconIdentifier = _keys[_keys.length - 1]; expect(icon.toLowerCase().includes(iconIdentifier)).toEqual(true); return this; } diff --git a/src/test/settingMenu/rebinding_setting.test.ts b/src/test/settingMenu/rebinding_setting.test.ts index ec2343cfb41..37cf8032897 100644 --- a/src/test/settingMenu/rebinding_setting.test.ts +++ b/src/test/settingMenu/rebinding_setting.test.ts @@ -22,7 +22,7 @@ describe("Test Rebinding", () => { beforeEach(() => { config = deepCopy(cfg_keyboard_qwerty); - config.custom = {...config.default}; + config.custom = { ...config.default }; configs["default"] = config; inGame = new InGameManip(configs, config, selectedDevice); inTheSettingMenu = new MenuManip(config); diff --git a/src/test/sprites/pokemonSprite.test.ts b/src/test/sprites/pokemonSprite.test.ts index faf0626b365..c29f88d3143 100644 --- a/src/test/sprites/pokemonSprite.test.ts +++ b/src/test/sprites/pokemonSprite.test.ts @@ -70,7 +70,7 @@ describe("check if every variant's sprite are correctly set", () => { errors.push(`[${id}] missing key ${id} in masterlist for ${trimmedFilePath}`); } if (mlist[id][index] === 1 && jsonFileExists) { - const raw = fs.readFileSync(urlJsonFile, {encoding: "utf8", flag: "r"}); + const raw = fs.readFileSync(urlJsonFile, { encoding: "utf8", flag: "r" }); const data = JSON.parse(raw); const keys = Object.keys(data); if (!keys.includes(`${index}`)) { @@ -87,7 +87,7 @@ describe("check if every variant's sprite are correctly set", () => { } else if (!mlist.hasOwnProperty(name)) { errors.push(`[${name}] - missing key ${name} in masterlist for ${trimmedFilePath}`); } else { - const raw = fs.readFileSync(filePath, {encoding: "utf8", flag: "r"}); + const raw = fs.readFileSync(filePath, { encoding: "utf8", flag: "r" }); const data = JSON.parse(raw); for (const key of Object.keys(data)) { if (mlist[name][key] !== 1) { @@ -109,14 +109,14 @@ describe("check if every variant's sprite are correctly set", () => { const errors: string[] = []; for (const key of Object.keys(keys)) { const row = keys[key]; - for (const [index, elm] of row.entries()) { + for (const [ index, elm ] of row.entries()) { let url: string; if (elm === 0) { continue; } else if (elm === 1) { url = `${key}.json`; const filePath = `${dirPath}${url}`; - const raw = fs.readFileSync(filePath, {encoding: "utf8", flag: "r"}); + const raw = fs.readFileSync(filePath, { encoding: "utf8", flag: "r" }); const data = JSON.parse(raw); if (!data.hasOwnProperty(index)) { errors.push(`index: ${index} - ${filePath}`); @@ -232,7 +232,7 @@ describe("check if every variant's sprite are correctly set", () => { it("look over every file in variant back male and check if present in masterlist", () => { const dirPath = `${rootDir}back${path.sep}`; const backMaleVariant = deepCopy(backVariant); - const errors = getMissingMasterlist(backMaleVariant, dirPath, ["female"]); + const errors = getMissingMasterlist(backMaleVariant, dirPath, [ "female" ]); if (errors.length) { console.log("errors for ", dirPath, errors); } @@ -259,7 +259,7 @@ describe("check if every variant's sprite are correctly set", () => { it("look over every file in variant exp male and check if present in masterlist", () => { const dirPath = `${rootDir}exp${path.sep}`; - const errors = getMissingMasterlist(expVariant, dirPath, ["back", "female"]); + const errors = getMissingMasterlist(expVariant, dirPath, [ "back", "female" ]); if (errors.length) { console.log("errors for ", dirPath, errors); } @@ -268,7 +268,7 @@ describe("check if every variant's sprite are correctly set", () => { it("look over every file in variant root and check if present in masterlist", () => { const dirPath = `${rootDir}`; - const errors = getMissingMasterlist(masterlist, dirPath, ["back", "female", "exp", "icons"]); + const errors = getMissingMasterlist(masterlist, dirPath, [ "back", "female", "exp", "icons" ]); if (errors.length) { console.log("errors for ", dirPath, errors); } diff --git a/src/test/system/game_data.test.ts b/src/test/system/game_data.test.ts index e3550e44fff..fcb7e9067a3 100644 --- a/src/test/system/game_data.test.ts +++ b/src/test/system/game_data.test.ts @@ -11,13 +11,15 @@ import * as account from "../../account"; const apiBase = import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8001"; -export const server = setupServer(); +/** We need a custom server. For some reasons I can't extend the listeners of {@linkcode global.i18nServer} with {@linkcode global.i18nServer.use} */ +const server = setupServer(); describe("System - Game Data", () => { let phaserGame: Phaser.Game; let game: GameManager; beforeAll(() => { + global.i18nServer.close(); server.listen(); phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -26,12 +28,13 @@ describe("System - Game Data", () => { afterAll(() => { server.close(); + global.i18nServer.listen(); }); beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.SPLASH]) + .moveset([ Moves.SPLASH ]) .battleType("single") .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH); @@ -46,7 +49,7 @@ describe("System - Game Data", () => { beforeEach(() => { vi.spyOn(BattleScene, "bypassLogin", "get").mockReturnValue(false); vi.spyOn(game.scene.gameData, "getSessionSaveData").mockReturnValue({} as SessionSaveData); - vi.spyOn(account, "updateUserInfo").mockImplementation(async () => [true, 1]); + vi.spyOn(account, "updateUserInfo").mockImplementation(async () => [ true, 1 ]); }); it("should return [true, true] if bypassLogin is true", async () => { @@ -54,7 +57,7 @@ describe("System - Game Data", () => { const result = await game.scene.gameData.tryClearSession(game.scene, 0); - expect(result).toEqual([true, true]); + expect(result).toEqual([ true, true ]); }); it("should return [true, true] if successful", async () => { @@ -62,7 +65,7 @@ describe("System - Game Data", () => { const result = await game.scene.gameData.tryClearSession(game.scene, 0); - expect(result).toEqual([true, true]); + expect(result).toEqual([ true, true ]); expect(account.updateUserInfo).toHaveBeenCalled(); }); @@ -71,7 +74,7 @@ describe("System - Game Data", () => { const result = await game.scene.gameData.tryClearSession(game.scene, 0); - expect(result).toEqual([true, false]); + expect(result).toEqual([ true, false ]); expect(account.updateUserInfo).toHaveBeenCalled(); }); @@ -82,7 +85,7 @@ describe("System - Game Data", () => { const result = await game.scene.gameData.tryClearSession(game.scene, 0); - expect(result).toEqual([false, false]); + expect(result).toEqual([ false, false ]); expect(account.updateUserInfo).toHaveBeenCalled(); }); }); diff --git a/src/test/ui/battle_info.test.ts b/src/test/ui/battle_info.test.ts index 4d511b75e6f..3100372f091 100644 --- a/src/test/ui/battle_info.test.ts +++ b/src/test/ui/battle_info.test.ts @@ -30,20 +30,20 @@ describe("UI - Battle Info", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([Moves.GUILLOTINE, Moves.SPLASH]) + .moveset([ Moves.GUILLOTINE, Moves.SPLASH ]) .battleType("single") .enemyAbility(Abilities.BALL_FETCH) .enemyMoveset(Moves.SPLASH) .enemySpecies(Species.CATERPIE); }); - it.each([ExpGainsSpeed.FAST, ExpGainsSpeed.FASTER, ExpGainsSpeed.SKIP])( + it.each([ ExpGainsSpeed.FAST, ExpGainsSpeed.FASTER, ExpGainsSpeed.SKIP ])( "should increase exp gains animation by 2^%i", async (expGainsSpeed) => { game.settings.expGainsSpeed(expGainsSpeed); vi.spyOn(Math, "pow"); - await game.classicMode.startBattle([Species.CHARIZARD]); + await game.classicMode.startBattle([ Species.CHARIZARD ]); game.move.select(Moves.SPLASH); await game.doKillOpponents(); diff --git a/src/test/ui/starter-select.test.ts b/src/test/ui/starter-select.test.ts index dd0761be392..94370ca1b74 100644 --- a/src/test/ui/starter-select.test.ts +++ b/src/test/ui/starter-select.test.ts @@ -14,6 +14,7 @@ import { Abilities } from "#enums/abilities"; import { Button } from "#enums/buttons"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; +import i18next from "i18next"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -66,11 +67,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - expect(options.some(option => option.label === "starterSelectUiHandler:addToParty")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:toggleIVs")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:manageMoves")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:useCandies")).toBe(true); - expect(options.some(option => option.label === "menu:cancel")).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:addToParty"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:toggleIVs"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:manageMoves"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:useCandies"))).toBe(true); + expect(options.some(option => option.label === i18next.t("menu:cancel"))).toBe(true); optionSelectUiHandler?.processInput(Button.ACTION); await new Promise((resolve) => { @@ -127,11 +128,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - expect(options.some(option => option.label === "starterSelectUiHandler:addToParty")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:toggleIVs")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:manageMoves")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:useCandies")).toBe(true); - expect(options.some(option => option.label === "menu:cancel")).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:addToParty"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:toggleIVs"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:manageMoves"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:useCandies"))).toBe(true); + expect(options.some(option => option.label === i18next.t("menu:cancel"))).toBe(true); optionSelectUiHandler?.processInput(Button.ACTION); await new Promise((resolve) => { @@ -191,11 +192,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - expect(options.some(option => option.label === "starterSelectUiHandler:addToParty")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:toggleIVs")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:manageMoves")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:useCandies")).toBe(true); - expect(options.some(option => option.label === "menu:cancel")).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:addToParty"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:toggleIVs"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:manageMoves"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:useCandies"))).toBe(true); + expect(options.some(option => option.label === i18next.t("menu:cancel"))).toBe(true); optionSelectUiHandler?.processInput(Button.ACTION); await new Promise((resolve) => { @@ -254,11 +255,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - expect(options.some(option => option.label === "starterSelectUiHandler:addToParty")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:toggleIVs")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:manageMoves")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:useCandies")).toBe(true); - expect(options.some(option => option.label === "menu:cancel")).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:addToParty"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:toggleIVs"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:manageMoves"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:useCandies"))).toBe(true); + expect(options.some(option => option.label === i18next.t("menu:cancel"))).toBe(true); optionSelectUiHandler?.processInput(Button.ACTION); await new Promise((resolve) => { @@ -315,11 +316,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - expect(options.some(option => option.label === "starterSelectUiHandler:addToParty")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:toggleIVs")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:manageMoves")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:useCandies")).toBe(true); - expect(options.some(option => option.label === "menu:cancel")).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:addToParty"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:toggleIVs"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:manageMoves"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:useCandies"))).toBe(true); + expect(options.some(option => option.label === i18next.t("menu:cancel"))).toBe(true); optionSelectUiHandler?.processInput(Button.ACTION); await new Promise((resolve) => { @@ -376,11 +377,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - expect(options.some(option => option.label === "starterSelectUiHandler:addToParty")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:toggleIVs")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:manageMoves")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:useCandies")).toBe(true); - expect(options.some(option => option.label === "menu:cancel")).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:addToParty"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:toggleIVs"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:manageMoves"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:useCandies"))).toBe(true); + expect(options.some(option => option.label === i18next.t("menu:cancel"))).toBe(true); optionSelectUiHandler?.processInput(Button.ACTION); await new Promise((resolve) => { @@ -436,11 +437,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - expect(options.some(option => option.label === "starterSelectUiHandler:addToParty")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:toggleIVs")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:manageMoves")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:useCandies")).toBe(true); - expect(options.some(option => option.label === "menu:cancel")).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:addToParty"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:toggleIVs"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:manageMoves"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:useCandies"))).toBe(true); + expect(options.some(option => option.label === i18next.t("menu:cancel"))).toBe(true); optionSelectUiHandler?.processInput(Button.ACTION); await new Promise((resolve) => { @@ -496,11 +497,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - expect(options.some(option => option.label === "starterSelectUiHandler:addToParty")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:toggleIVs")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:manageMoves")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:useCandies")).toBe(true); - expect(options.some(option => option.label === "menu:cancel")).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:addToParty"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:toggleIVs"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:manageMoves"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:useCandies"))).toBe(true); + expect(options.some(option => option.label === i18next.t("menu:cancel"))).toBe(true); optionSelectUiHandler?.processInput(Button.ACTION); let starterSelectUiHandler: StarterSelectUiHandler; @@ -561,11 +562,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - expect(options.some(option => option.label === "starterSelectUiHandler:addToParty")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:toggleIVs")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:manageMoves")).toBe(true); - expect(options.some(option => option.label === "starterSelectUiHandler:useCandies")).toBe(true); - expect(options.some(option => option.label === "menu:cancel")).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:addToParty"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:toggleIVs"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:manageMoves"))).toBe(true); + expect(options.some(option => option.label === i18next.t("starterSelectUiHandler:useCandies"))).toBe(true); + expect(options.some(option => option.label === i18next.t("menu:cancel"))).toBe(true); optionSelectUiHandler?.processInput(Button.ACTION); let starterSelectUiHandler: StarterSelectUiHandler | undefined; diff --git a/src/test/ui/transfer-item.test.ts b/src/test/ui/transfer-item.test.ts index f7dea463574..0fbd4a52c61 100644 --- a/src/test/ui/transfer-item.test.ts +++ b/src/test/ui/transfer-item.test.ts @@ -37,11 +37,11 @@ describe("UI - Transfer Items", () => { { name: "BERRY", count: 2, type: BerryType.APICOT }, { name: "BERRY", count: 2, type: BerryType.LUM }, ]); - game.override.moveset([Moves.DRAGON_CLAW]); + game.override.moveset([ Moves.DRAGON_CLAW ]); game.override.enemySpecies(Species.MAGIKARP); - game.override.enemyMoveset([Moves.SPLASH]); + game.override.enemyMoveset([ Moves.SPLASH ]); - await game.startBattle([Species.RAYQUAZA, Species.RAYQUAZA, Species.RAYQUAZA]); + await game.startBattle([ Species.RAYQUAZA, Species.RAYQUAZA, Species.RAYQUAZA ]); game.move.select(Moves.DRAGON_CLAW); diff --git a/src/test/ui/type-hints.test.ts b/src/test/ui/type-hints.test.ts index 82209859fb0..2977262dda7 100644 --- a/src/test/ui/type-hints.test.ts +++ b/src/test/ui/type-hints.test.ts @@ -7,7 +7,8 @@ import { Mode } from "#app/ui/ui"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import MockText from "../utils/mocks/mocksContainer/mockText"; +import MockText from "#test/utils/mocks/mocksContainer/mockText"; +import i18next from "i18next"; describe("UI - Type Hints", () => { let phaserGame: Phaser.Game; @@ -36,10 +37,10 @@ describe("UI - Type Hints", () => { .startingWave(1) .enemySpecies(Species.FLORGES) .enemyMoveset(Moves.SPLASH) - .moveset([Moves.DRAGON_CLAW]); + .moveset([ Moves.DRAGON_CLAW ]); game.settings.typeHints(true); //activate type hints - await game.startBattle([Species.RAYQUAZA]); + await game.startBattle([ Species.RAYQUAZA ]); game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { const { ui } = game.scene; @@ -53,7 +54,7 @@ describe("UI - Type Hints", () => { const movesContainer = ui.getByName(FightUiHandler.MOVES_CONTAINER_NAME); const dragonClawText = movesContainer .getAll() - .find((text) => text.text === "move:dragonClaw.name")! as unknown as MockText; + .find((text) => text.text === i18next.t("move:dragonClaw.name"))! as unknown as MockText; expect.soft(dragonClawText.color).toBe("#929292"); ui.getHandler().processInput(Button.ACTION); @@ -62,9 +63,9 @@ describe("UI - Type Hints", () => { }); it("check status move color", async () => { - game.override.enemySpecies(Species.FLORGES).moveset([Moves.GROWL]); + game.override.enemySpecies(Species.FLORGES).moveset([ Moves.GROWL ]); - await game.startBattle([Species.RAYQUAZA]); + await game.startBattle([ Species.RAYQUAZA ]); game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { const { ui } = game.scene; @@ -78,7 +79,7 @@ describe("UI - Type Hints", () => { const movesContainer = ui.getByName(FightUiHandler.MOVES_CONTAINER_NAME); const growlText = movesContainer .getAll() - .find((text) => text.text === "move:growl.name")! as unknown as MockText; + .find((text) => text.text === i18next.t("move:growl.name"))! as unknown as MockText; expect.soft(growlText.color).toBe(undefined); ui.getHandler().processInput(Button.ACTION); diff --git a/src/test/utils/gameManager.ts b/src/test/utils/gameManager.ts index a2403de7e18..86c51972c8b 100644 --- a/src/test/utils/gameManager.ts +++ b/src/test/utils/gameManager.ts @@ -304,7 +304,7 @@ export default class GameManager { vi.spyOn(enemy, "getNextMove").mockReturnValueOnce({ move: moveId, targets: (target !== undefined && !legalTargets.multiple && legalTargets.targets.includes(target)) - ? [target] + ? [ target ] : enemy.getNextTargets(moveId) }); @@ -320,7 +320,7 @@ export default class GameManager { const originalMatchupScore = Trainer.prototype.getPartyMemberMatchupScores; Trainer.prototype.getPartyMemberMatchupScores = () => { Trainer.prototype.getPartyMemberMatchupScores = originalMatchupScore; - return [[1, 100], [1, 100]]; + return [[ 1, 100 ], [ 1, 100 ]]; }; } diff --git a/src/test/utils/gameManagerUtils.ts b/src/test/utils/gameManagerUtils.ts index 700d93082d8..543ee9627fe 100644 --- a/src/test/utils/gameManagerUtils.ts +++ b/src/test/utils/gameManagerUtils.ts @@ -86,7 +86,7 @@ export function waitUntil(truth) { export function getMovePosition(scene: BattleScene, pokemonIndex: 0 | 1, move: Moves) { const playerPokemon = scene.getPlayerField()[pokemonIndex]; const moveSet = playerPokemon.getMoveset(); - const index = moveSet.findIndex((m) => m?.moveId === move); + const index = moveSet.findIndex((m) => m?.moveId === move && m?.ppUsed < m?.getMovePp()); console.log(`Move position for ${Moves[move]} (=${move}):`, index); return index; } diff --git a/src/test/utils/gameWrapper.ts b/src/test/utils/gameWrapper.ts index 0ef5c4d4611..48c0007118b 100644 --- a/src/test/utils/gameWrapper.ts +++ b/src/test/utils/gameWrapper.ts @@ -23,6 +23,7 @@ import KeyboardPlugin = Phaser.Input.Keyboard.KeyboardPlugin; import GamepadPlugin = Phaser.Input.Gamepad.GamepadPlugin; import EventEmitter = Phaser.Events.EventEmitter; import UpdateList = Phaser.GameObjects.UpdateList; +import { version } from "../../../package.json"; Object.defineProperty(window, "localStorage", { value: mockLocalStorage(), @@ -101,6 +102,7 @@ export default class GameWrapper { injectMandatory() { this.game.config = { seed: ["test"], + gameVersion: version }; this.scene.game = this.game; this.game.renderer = { diff --git a/src/test/utils/helpers/moveHelper.ts b/src/test/utils/helpers/moveHelper.ts index a53fa521785..a0667d91f4c 100644 --- a/src/test/utils/helpers/moveHelper.ts +++ b/src/test/utils/helpers/moveHelper.ts @@ -13,8 +13,8 @@ import { GameManagerHelper } from "./gameManagerHelper"; */ export class MoveHelper extends GameManagerHelper { /** - * Intercepts `MoveEffectPhase` and mocks the hitCheck's - * return value to `true` {@linkcode MoveEffectPhase.hitCheck}. + * Intercepts {@linkcode MoveEffectPhase} and mocks the + * {@linkcode MoveEffectPhase.hitCheck | hitCheck}'s return value to `true`. * Used to force a move to hit. */ async forceHit(): Promise { @@ -23,8 +23,8 @@ export class MoveHelper extends GameManagerHelper { } /** - * Intercepts `MoveEffectPhase` and mocks the hitCheck's - * return value to `false` {@linkcode MoveEffectPhase.hitCheck}. + * Intercepts {@linkcode MoveEffectPhase} and mocks the + * {@linkcode MoveEffectPhase.hitCheck | hitCheck}'s return value to `false`. * Used to force a move to miss. * @param firstTargetOnly Whether the move should force miss on the first target only, in the case of multi-target moves. */ diff --git a/src/test/utils/helpers/overridesHelper.ts b/src/test/utils/helpers/overridesHelper.ts index 84cb1719e0b..27fd9552fe4 100644 --- a/src/test/utils/helpers/overridesHelper.ts +++ b/src/test/utils/helpers/overridesHelper.ts @@ -85,6 +85,27 @@ export class OverridesHelper extends GameManagerHelper { return this; } + /** + * Override the player (pokemon) to be a random fusion + * @returns this + */ + enableStarterFusion(): this { + vi.spyOn(Overrides, "STARTER_FUSION_OVERRIDE", "get").mockReturnValue(true); + this.log("Player Pokemon is a random fusion!"); + return this; + } + + /** + * Override the player (pokemon) fusion species + * @param species the fusion species to set + * @returns this + */ + starterFusionSpecies(species: Species | number): this { + vi.spyOn(Overrides, "STARTER_FUSION_SPECIES_OVERRIDE", "get").mockReturnValue(species); + this.log(`Player Pokemon fusion species set to ${Species[species]} (=${species})!`); + return this; + } + /** * Override the player (pokemons) forms * @param forms the (pokemon) forms to set @@ -93,7 +114,7 @@ export class OverridesHelper extends GameManagerHelper { starterForms(forms: Partial>): this { vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue(forms); const formsStr = Object.entries(forms) - .map(([speciesId, formIndex]) => `${Species[speciesId]}=${formIndex}`) + .map(([ speciesId, formIndex ]) => `${Species[speciesId]}=${formIndex}`) .join(", "); this.log(`Player Pokemon form set to: ${formsStr}!`); return this; @@ -140,7 +161,7 @@ export class OverridesHelper extends GameManagerHelper { moveset(moveset: Moves | Moves[]): this { vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(moveset); if (!Array.isArray(moveset)) { - moveset = [moveset]; + moveset = [ moveset ]; } const movesetStr = moveset.map((moveId) => Moves[moveId]).join(", "); this.log(`Player Pokemon moveset set to ${movesetStr} (=[${moveset.join(", ")}])!`); @@ -202,7 +223,7 @@ export class OverridesHelper extends GameManagerHelper { seed(seed: string): this { vi.spyOn(this.game.scene, "resetSeed").mockImplementation(() => { this.game.scene.waveSeed = seed; - Phaser.Math.RND.sow([seed]); + Phaser.Math.RND.sow([ seed ]); this.game.scene.rngCounter = 0; }); this.game.scene.resetSeed(); @@ -232,6 +253,27 @@ export class OverridesHelper extends GameManagerHelper { return this; } + /** + * Override the enemy (pokemon) to be a random fusion + * @returns this + */ + enableEnemyFusion(): this { + vi.spyOn(Overrides, "OPP_FUSION_OVERRIDE", "get").mockReturnValue(true); + this.log("Enemy Pokemon is a random fusion!"); + return this; + } + + /** + * Override the enemy (pokemon) fusion species + * @param species the fusion species to set + * @returns this + */ + enemyFusionSpecies(species: Species | number): this { + vi.spyOn(Overrides, "OPP_FUSION_SPECIES_OVERRIDE", "get").mockReturnValue(species); + this.log(`Enemy Pokemon fusion species set to ${Species[species]} (=${species})!`); + return this; + } + /** * Override the enemy (pokemon) {@linkcode Abilities | ability} * @param ability the (pokemon) {@linkcode Abilities | ability} to set @@ -262,7 +304,7 @@ export class OverridesHelper extends GameManagerHelper { enemyMoveset(moveset: Moves | Moves[]): this { vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(moveset); if (!Array.isArray(moveset)) { - moveset = [moveset]; + moveset = [ moveset ]; } const movesetStr = moveset.map((moveId) => Moves[moveId]).join(", "); this.log(`Enemy Pokemon moveset set to ${movesetStr} (=[${moveset.join(", ")}])!`); diff --git a/src/test/utils/helpers/settingsHelper.ts b/src/test/utils/helpers/settingsHelper.ts index c611a705107..83baa329cec 100644 --- a/src/test/utils/helpers/settingsHelper.ts +++ b/src/test/utils/helpers/settingsHelper.ts @@ -27,7 +27,7 @@ export class SettingsHelper extends GameManagerHelper { */ typeHints(enable: boolean): void { this.game.scene.typeHints = enable; - this.log(`Type Hints ${enable? "enabled" : "disabled"}` ); + this.log(`Type Hints ${enable ? "enabled" : "disabled"}` ); } /** diff --git a/src/test/utils/inputsHandler.ts b/src/test/utils/inputsHandler.ts index 30dd101f43d..bf690d5d74c 100644 --- a/src/test/utils/inputsHandler.ts +++ b/src/test/utils/inputsHandler.ts @@ -41,18 +41,18 @@ export default class InputsHandler { pressGamepadButton(button: integer, duration: integer): Promise { return new Promise(async (resolve) => { - this.scene.input.gamepad?.emit("down", this.fakePad, {index: button}); + this.scene.input.gamepad?.emit("down", this.fakePad, { index: button }); await holdOn(duration); - this.scene.input.gamepad?.emit("up", this.fakePad, {index: button}); + this.scene.input.gamepad?.emit("up", this.fakePad, { index: button }); resolve(); }); } pressKeyboardKey(key: integer, duration: integer): Promise { return new Promise(async (resolve) => { - this.scene.input.keyboard?.emit("keydown", {keyCode: key}); + this.scene.input.keyboard?.emit("keydown", { keyCode: key }); await holdOn(duration); - this.scene.input.keyboard?.emit("keyup", {keyCode: key}); + this.scene.input.keyboard?.emit("keyup", { keyCode: key }); resolve(); }); } @@ -67,11 +67,11 @@ export default class InputsHandler { listenInputs(): void { this.events.on("input_down", (event) => { - this.log.push({type: "input_down", button: event.button}); + this.log.push({ type: "input_down", button: event.button }); }, this); this.events.on("input_up", (event) => { - this.logUp.push({type: "input_up", button: event.button}); + this.logUp.push({ type: "input_up", button: event.button }); }, this); } } @@ -82,7 +82,7 @@ class Fakepad extends Phaser.Input.Gamepad.Gamepad { constructor(pad) { //@ts-ignore - super(undefined, {...pad, buttons: pad.deviceMapping, axes: []}); //TODO: resolve ts-ignore + super(undefined, { ...pad, buttons: pad.deviceMapping, axes: []}); //TODO: resolve ts-ignore this.id = "xbox_360_fakepad"; this.index = 0; } @@ -90,7 +90,7 @@ class Fakepad extends Phaser.Input.Gamepad.Gamepad { class FakeMobile { constructor() { - const fakeMobilePage = fs.readFileSync("./src/test/utils/fakeMobile.html", {encoding: "utf8", flag: "r"}); + const fakeMobilePage = fs.readFileSync("./src/test/utils/fakeMobile.html", { encoding: "utf8", flag: "r" }); const dom = new JSDOM(fakeMobilePage); Object.defineProperty(window, "document", { value: dom.window.document, diff --git a/src/test/utils/mocks/mockClock.ts b/src/test/utils/mocks/mockClock.ts index e7501a7c99d..7fad3651010 100644 --- a/src/test/utils/mocks/mockClock.ts +++ b/src/test/utils/mocks/mockClock.ts @@ -17,7 +17,7 @@ export class MockClock extends Clock { } addEvent(config: Phaser.Time.TimerEvent | Phaser.Types.Time.TimerEventConfig): Phaser.Time.TimerEvent { - const cfg = { ...config, delay: this.overrideDelay ?? config.delay}; + const cfg = { ...config, delay: this.overrideDelay ?? config.delay }; return super.addEvent(cfg); } } diff --git a/src/test/utils/mocks/mockConsoleLog.ts b/src/test/utils/mocks/mockConsoleLog.ts index f44a0c7d6cd..9c3cbca6bb6 100644 --- a/src/test/utils/mocks/mockConsoleLog.ts +++ b/src/test/utils/mocks/mockConsoleLog.ts @@ -1,4 +1,4 @@ -const MockConsoleLog = (_logDisabled= false, _phaseText=false) => { +const MockConsoleLog = (_logDisabled = false, _phaseText = false) => { let logs: any[] = []; const logDisabled: boolean = _logDisabled; const phaseText: boolean = _phaseText; @@ -8,8 +8,8 @@ const MockConsoleLog = (_logDisabled= false, _phaseText=false) => { const originalWarn = console.warn; const notified: any[] = []; - const blacklist = ["Phaser", "variant icon does not exist", "Texture \"%s\" not found"]; - const whitelist = ["Phase"]; + const blacklist = [ "Phaser", "variant icon does not exist", "Texture \"%s\" not found" ]; + const whitelist = [ "Phase" ]; return ({ log(...args) { diff --git a/src/test/utils/mocks/mockFetch.ts b/src/test/utils/mocks/mockFetch.ts index ad3758775d1..2fa7cd198ce 100644 --- a/src/test/utils/mocks/mockFetch.ts +++ b/src/test/utils/mocks/mockFetch.ts @@ -5,12 +5,12 @@ export const MockFetch = (input, init) => { let responseText; const handlers = { - "account/info": {"username":"greenlamp", "lastSessionSlot":0}, + "account/info": { "username":"greenlamp", "lastSessionSlot":0 }, "savedata/session": {}, "savedata/system": {}, "savedata/updateall": "", "daily/rankingpagecount": { data: 0 }, - "game/titlestats": {"playerCount":0, "battleCount":5}, + "game/titlestats": { "playerCount":0, "battleCount":5 }, "daily/rankings": [], }; diff --git a/src/test/utils/mocks/mocksContainer/mockSprite.ts b/src/test/utils/mocks/mocksContainer/mockSprite.ts index a55b218d0c2..e726fec454d 100644 --- a/src/test/utils/mocks/mocksContainer/mockSprite.ts +++ b/src/test/utils/mocks/mocksContainer/mockSprite.ts @@ -212,5 +212,4 @@ export default class MockSprite implements MockGameObject { } - } diff --git a/src/test/utils/phaseInterceptor.ts b/src/test/utils/phaseInterceptor.ts index 6c4c9a6cf94..ec9309e2405 100644 --- a/src/test/utils/phaseInterceptor.ts +++ b/src/test/utils/phaseInterceptor.ts @@ -53,6 +53,7 @@ import { } from "#app/phases/mystery-encounter-phases"; import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase"; import { PartyExpPhase } from "#app/phases/party-exp-phase"; +import { ExpPhase } from "#app/phases/exp-phase"; export interface PromptHandler { phaseTarget?: string; @@ -61,7 +62,114 @@ export interface PromptHandler { expireFn?: () => void; awaitingActionInput?: boolean; } -import { ExpPhase } from "#app/phases/exp-phase"; + +type PhaseClass = + | typeof LoginPhase + | typeof TitlePhase + | typeof SelectGenderPhase + | typeof EncounterPhase + | typeof NewBiomeEncounterPhase + | typeof SelectStarterPhase + | typeof PostSummonPhase + | typeof SummonPhase + | typeof ToggleDoublePositionPhase + | typeof CheckSwitchPhase + | typeof ShowAbilityPhase + | typeof MessagePhase + | typeof TurnInitPhase + | typeof CommandPhase + | typeof EnemyCommandPhase + | typeof TurnStartPhase + | typeof MovePhase + | typeof MoveEffectPhase + | typeof DamagePhase + | typeof FaintPhase + | typeof BerryPhase + | typeof TurnEndPhase + | typeof BattleEndPhase + | typeof EggLapsePhase + | typeof SelectModifierPhase + | typeof NextEncounterPhase + | typeof NewBattlePhase + | typeof VictoryPhase + | typeof LearnMovePhase + | typeof MoveEndPhase + | typeof StatStageChangePhase + | typeof ShinySparklePhase + | typeof SelectTargetPhase + | typeof UnavailablePhase + | typeof QuietFormChangePhase + | typeof SwitchPhase + | typeof SwitchSummonPhase + | typeof PartyHealPhase + | typeof EvolutionPhase + | typeof EndEvolutionPhase + | typeof LevelCapPhase + | typeof AttemptRunPhase + | typeof SelectBiomePhase + | typeof MysteryEncounterPhase + | typeof MysteryEncounterOptionSelectedPhase + | typeof MysteryEncounterBattlePhase + | typeof MysteryEncounterRewardsPhase + | typeof PostMysteryEncounterPhase + | typeof ModifierRewardPhase + | typeof PartyExpPhase + | typeof ExpPhase; + +type PhaseString = + | "LoginPhase" + | "TitlePhase" + | "SelectGenderPhase" + | "EncounterPhase" + | "NewBiomeEncounterPhase" + | "SelectStarterPhase" + | "PostSummonPhase" + | "SummonPhase" + | "ToggleDoublePositionPhase" + | "CheckSwitchPhase" + | "ShowAbilityPhase" + | "MessagePhase" + | "TurnInitPhase" + | "CommandPhase" + | "EnemyCommandPhase" + | "TurnStartPhase" + | "MovePhase" + | "MoveEffectPhase" + | "DamagePhase" + | "FaintPhase" + | "BerryPhase" + | "TurnEndPhase" + | "BattleEndPhase" + | "EggLapsePhase" + | "SelectModifierPhase" + | "NextEncounterPhase" + | "NewBattlePhase" + | "VictoryPhase" + | "LearnMovePhase" + | "MoveEndPhase" + | "StatStageChangePhase" + | "ShinySparklePhase" + | "SelectTargetPhase" + | "UnavailablePhase" + | "QuietFormChangePhase" + | "SwitchPhase" + | "SwitchSummonPhase" + | "PartyHealPhase" + | "EvolutionPhase" + | "EndEvolutionPhase" + | "LevelCapPhase" + | "AttemptRunPhase" + | "SelectBiomePhase" + | "MysteryEncounterPhase" + | "MysteryEncounterOptionSelectedPhase" + | "MysteryEncounterBattlePhase" + | "MysteryEncounterRewardsPhase" + | "PostMysteryEncounterPhase" + | "ModifierRewardPhase" + | "PartyExpPhase" + | "ExpPhase"; + +type PhaseInterceptorPhase = PhaseClass | PhaseString; export default class PhaseInterceptor { public scene; @@ -81,57 +189,57 @@ export default class PhaseInterceptor { * List of phases with their corresponding start methods. */ private PHASES = [ - [LoginPhase, this.startPhase], - [TitlePhase, this.startPhase], - [SelectGenderPhase, this.startPhase], - [EncounterPhase, this.startPhase], - [NewBiomeEncounterPhase, this.startPhase], - [SelectStarterPhase, this.startPhase], - [PostSummonPhase, this.startPhase], - [SummonPhase, this.startPhase], - [ToggleDoublePositionPhase, this.startPhase], - [CheckSwitchPhase, this.startPhase], - [ShowAbilityPhase, this.startPhase], - [MessagePhase, this.startPhase], - [TurnInitPhase, this.startPhase], - [CommandPhase, this.startPhase], - [EnemyCommandPhase, this.startPhase], - [TurnStartPhase, this.startPhase], - [MovePhase, this.startPhase], - [MoveEffectPhase, this.startPhase], - [DamagePhase, this.startPhase], - [FaintPhase, this.startPhase], - [BerryPhase, this.startPhase], - [TurnEndPhase, this.startPhase], - [BattleEndPhase, this.startPhase], - [EggLapsePhase, this.startPhase], - [SelectModifierPhase, this.startPhase], - [NextEncounterPhase, this.startPhase], - [NewBattlePhase, this.startPhase], - [VictoryPhase, this.startPhase], - [LearnMovePhase, this.startPhase], - [MoveEndPhase, this.startPhase], - [StatStageChangePhase, this.startPhase], - [ShinySparklePhase, this.startPhase], - [SelectTargetPhase, this.startPhase], - [UnavailablePhase, this.startPhase], - [QuietFormChangePhase, this.startPhase], - [SwitchPhase, this.startPhase], - [SwitchSummonPhase, this.startPhase], - [PartyHealPhase, this.startPhase], - [EvolutionPhase, this.startPhase], - [EndEvolutionPhase, this.startPhase], - [LevelCapPhase, this.startPhase], - [AttemptRunPhase, this.startPhase], - [SelectBiomePhase, this.startPhase], - [MysteryEncounterPhase, this.startPhase], - [MysteryEncounterOptionSelectedPhase, this.startPhase], - [MysteryEncounterBattlePhase, this.startPhase], - [MysteryEncounterRewardsPhase, this.startPhase], - [PostMysteryEncounterPhase, this.startPhase], - [ModifierRewardPhase, this.startPhase], - [PartyExpPhase, this.startPhase], - [ExpPhase, this.startPhase], + [ LoginPhase, this.startPhase ], + [ TitlePhase, this.startPhase ], + [ SelectGenderPhase, this.startPhase ], + [ EncounterPhase, this.startPhase ], + [ NewBiomeEncounterPhase, this.startPhase ], + [ SelectStarterPhase, this.startPhase ], + [ PostSummonPhase, this.startPhase ], + [ SummonPhase, this.startPhase ], + [ ToggleDoublePositionPhase, this.startPhase ], + [ CheckSwitchPhase, this.startPhase ], + [ ShowAbilityPhase, this.startPhase ], + [ MessagePhase, this.startPhase ], + [ TurnInitPhase, this.startPhase ], + [ CommandPhase, this.startPhase ], + [ EnemyCommandPhase, this.startPhase ], + [ TurnStartPhase, this.startPhase ], + [ MovePhase, this.startPhase ], + [ MoveEffectPhase, this.startPhase ], + [ DamagePhase, this.startPhase ], + [ FaintPhase, this.startPhase ], + [ BerryPhase, this.startPhase ], + [ TurnEndPhase, this.startPhase ], + [ BattleEndPhase, this.startPhase ], + [ EggLapsePhase, this.startPhase ], + [ SelectModifierPhase, this.startPhase ], + [ NextEncounterPhase, this.startPhase ], + [ NewBattlePhase, this.startPhase ], + [ VictoryPhase, this.startPhase ], + [ LearnMovePhase, this.startPhase ], + [ MoveEndPhase, this.startPhase ], + [ StatStageChangePhase, this.startPhase ], + [ ShinySparklePhase, this.startPhase ], + [ SelectTargetPhase, this.startPhase ], + [ UnavailablePhase, this.startPhase ], + [ QuietFormChangePhase, this.startPhase ], + [ SwitchPhase, this.startPhase ], + [ SwitchSummonPhase, this.startPhase ], + [ PartyHealPhase, this.startPhase ], + [ EvolutionPhase, this.startPhase ], + [ EndEvolutionPhase, this.startPhase ], + [ LevelCapPhase, this.startPhase ], + [ AttemptRunPhase, this.startPhase ], + [ SelectBiomePhase, this.startPhase ], + [ MysteryEncounterPhase, this.startPhase ], + [ MysteryEncounterOptionSelectedPhase, this.startPhase ], + [ MysteryEncounterBattlePhase, this.startPhase ], + [ MysteryEncounterRewardsPhase, this.startPhase ], + [ PostMysteryEncounterPhase, this.startPhase ], + [ ModifierRewardPhase, this.startPhase ], + [ PartyExpPhase, this.startPhase ], + [ ExpPhase, this.startPhase ], ]; private endBySetMode = [ @@ -172,7 +280,7 @@ export default class PhaseInterceptor { * @param phaseFrom - The phase to start from. * @returns The instance of the PhaseInterceptor. */ - runFrom(phaseFrom) { + runFrom(phaseFrom: PhaseInterceptorPhase): PhaseInterceptor { this.phaseFrom = phaseFrom; return this; } @@ -180,9 +288,10 @@ export default class PhaseInterceptor { /** * Method to transition to a target phase. * @param phaseTo - The phase to transition to. + * @param runTarget - Whether or not to run the target phase. * @returns A promise that resolves when the transition is complete. */ - async to(phaseTo, runTarget: boolean = true): Promise { + async to(phaseTo: PhaseInterceptorPhase, runTarget: boolean = true): Promise { return new Promise(async (resolve, reject) => { ErrorInterceptor.getInstance().add(this); if (this.phaseFrom) { @@ -219,7 +328,7 @@ export default class PhaseInterceptor { * @param skipFn - Optional skip function. * @returns A promise that resolves when the phase is run. */ - run(phaseTarget, skipFn?): Promise { + run(phaseTarget: PhaseInterceptorPhase, skipFn?: (className: PhaseClass) => boolean): Promise { const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name; this.scene.moveAnimations = null; // Mandatory to avoid crash return new Promise(async (resolve, reject) => { @@ -253,7 +362,7 @@ export default class PhaseInterceptor { }); } - whenAboutToRun(phaseTarget, skipFn?): Promise { + whenAboutToRun(phaseTarget: PhaseInterceptorPhase, skipFn?: (className: PhaseClass) => boolean): Promise { const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name; this.scene.moveAnimations = null; // Mandatory to avoid crash return new Promise(async (resolve, reject) => { @@ -297,7 +406,7 @@ export default class PhaseInterceptor { this.originalSuperEnd = Phase.prototype.end; UI.prototype.setMode = (mode, ...args) => this.setMode.call(this, mode, ...args); Phase.prototype.end = () => this.superEndPhase.call(this); - for (const [phase, methodStart] of this.PHASES) { + for (const [ phase, methodStart ] of this.PHASES) { const originalStart = phase.prototype.start; this.phases[phase.name] = { start: originalStart, @@ -311,7 +420,7 @@ export default class PhaseInterceptor { * Method to start a phase and log it. * @param phase - The phase to start. */ - startPhase(phase) { + startPhase(phase: PhaseClass) { this.log.push(phase.name); const instance = this.scene.getCurrentPhase(); this.onHold.push({ @@ -340,13 +449,14 @@ export default class PhaseInterceptor { /** * m2m to set mode. - * @param phase - The phase to start. + * @param mode - The {@linkcode Mode} to set. + * @param args - Additional arguments to pass to the original method. */ - setMode(mode: Mode, ...args: any[]): Promise { + setMode(mode: Mode, ...args: unknown[]): Promise { const currentPhase = this.scene.getCurrentPhase(); const instance = this.scene.ui; console.log("setMode", `${Mode[mode]} (=${mode})`, args); - const ret = this.originalSetMode.apply(instance, [mode, ...args]); + const ret = this.originalSetMode.apply(instance, [ mode, ...args ]); if (!this.phases[currentPhase.constructor.name]) { throw new Error(`missing ${currentPhase.constructor.name} in phaseInterceptor PHASES list --- Add it to PHASES inside of /test/utils/phaseInterceptor.ts`); @@ -406,7 +516,7 @@ export default class PhaseInterceptor { * function stored in `this.phases`. Additionally, it clears the `promptInterval` and `interval`. */ restoreOg() { - for (const [phase] of this.PHASES) { + for (const [ phase ] of this.PHASES) { phase.prototype.start = this.phases[phase.name].start; } UI.prototype.setMode = this.originalSetMode; diff --git a/src/test/vitest.setup.ts b/src/test/vitest.setup.ts index 948180ca261..8438f607db2 100644 --- a/src/test/vitest.setup.ts +++ b/src/test/vitest.setup.ts @@ -4,16 +4,17 @@ import { initLoggedInUser } from "#app/account"; import { initAbilities } from "#app/data/ability"; import { initBiomes } from "#app/data/balance/biomes"; import { initEggMoves } from "#app/data/balance/egg-moves"; +import { initPokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { initMoves } from "#app/data/move"; import { initMysteryEncounters } from "#app/data/mystery-encounters/mystery-encounters"; -import { initPokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { initPokemonForms } from "#app/data/pokemon-forms"; import { initSpecies } from "#app/data/pokemon-species"; import { initAchievements } from "#app/system/achv"; import { initVouchers } from "#app/system/voucher"; import { initStatsKeys } from "#app/ui/game-stats-ui-handler"; -import { beforeAll, vi } from "vitest"; +import { afterAll, beforeAll, vi } from "vitest"; +/** Set the timezone to UTC for tests. */ process.env.TZ = "UTC"; /** Mock the override import to always return default values, ignoring any custom overrides. */ @@ -26,26 +27,36 @@ vi.mock("#app/overrides", async (importOriginal) => { } satisfies typeof import("#app/overrides"); }); -vi.mock("i18next", () => ({ - default: { - use: () => {}, - t: (key: string) => key, - changeLanguage: () => Promise.resolve(), - init: () => Promise.resolve(), - resolvedLanguage: "en", - exists: () => true, - getDataByLanguage:() => ({ - en: { - keys: ["foo"] - }, - }), - services: { - formatter: { - add: () => {}, +/** + * This is a hacky way to mock the i18n backend requests (with the help of {@link https://mswjs.io/ | msw}). + * The reason to put it inside of a mock is to elevate it. + * This is necessary because how our code is structured. + * Do NOT try to put any of this code into external functions, it won't work as it's elevated during runtime. + */ +vi.mock("i18next", async (importOriginal) => { + console.log("Mocking i18next"); + const { setupServer } = await import("msw/node"); + const { http, HttpResponse } = await import("msw"); + + global.i18nServer = setupServer( + http.get("/locales/en/*", async (req) => { + const filename = req.params[0]; + + try { + const json = await import(`../../public/locales/en/${req.params[0]}`); + console.log("Loaded locale", filename); + return HttpResponse.json(json); + } catch (err) { + console.log(`Failed to load locale ${filename}!`, err); + return HttpResponse.json({}); } - }, - }, -})); + }) + ); + global.i18nServer.listen({ onUnhandledRequest: "error" }); + console.log("i18n MSW server listening!"); + + return await importOriginal(); +}); initVouchers(); initAchievements(); @@ -70,3 +81,8 @@ beforeAll(() => { }, }); }); + +afterAll(() => { + global.i18nServer.close(); + console.log("Closing i18n MSW server!"); +}); diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 3caa84fd39b..513d21bd2f3 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -34,7 +34,7 @@ const timedEvents: TimedEvent[] = [ xPosition: 19, yPosition: 120, scale: 0.21, - availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN"] + availableLangs: [ "en", "de", "it", "fr", "ja", "ko", "es", "pt-BR", "zh-CN" ] } ]; @@ -95,7 +95,7 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container { let key = this.event.bannerKey; if (lang && this.event.availableLangs && this.event.availableLangs.length > 0) { if (this.event.availableLangs.includes(lang)) { - key += "_"+lang; + key += "_" + lang; } else { key += "_en"; } @@ -142,7 +142,7 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container { // Utility to add leading zero function z(n) { - return (n < 10? "0" : "") + n; + return (n < 10 ? "0" : "") + n; } const now = new Date(); let diff = Math.abs(date.getTime() - now.getTime()); @@ -151,13 +151,13 @@ export class TimedEventDisplay extends Phaser.GameObjects.Container { diff = Math.abs(diff); // Get time components - const days = diff/8.64e7 | 0; - const hours = diff%8.64e7 / 3.6e6 | 0; - const mins = diff%3.6e6 / 6e4 | 0; - const secs = Math.round(diff%6e4 / 1e3); + const days = diff / 8.64e7 | 0; + const hours = diff % 8.64e7 / 3.6e6 | 0; + const mins = diff % 3.6e6 / 6e4 | 0; + const secs = Math.round(diff % 6e4 / 1e3); // Return formatted string - return "Event Ends in : " + z(days) + "d " + z(hours) + "h " + z(mins) + "m " + z(secs)+ "s"; + return "Event Ends in : " + z(days) + "d " + z(hours) + "h " + z(mins) + "m " + z(secs) + "s"; } updateCountdown() { diff --git a/src/touch-controls.ts b/src/touch-controls.ts index 53df545e27f..93032ce59fe 100644 --- a/src/touch-controls.ts +++ b/src/touch-controls.ts @@ -1,4 +1,4 @@ -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import EventEmitter = Phaser.Events.EventEmitter; import BattleScene from "./battle-scene"; @@ -122,20 +122,20 @@ export default class TouchControl { const button = Button[key]; switch (eventType) { - case "keydown": - this.events.emit("input_down", { - controller_type: "keyboard", - button: button, - isTouch: true - }); - break; - case "keyup": - this.events.emit("input_up", { - controller_type: "keyboard", - button: button, - isTouch: true - }); - break; + case "keydown": + this.events.emit("input_down", { + controller_type: "keyboard", + button: button, + isTouch: true + }); + break; + case "keyup": + this.events.emit("input_up", { + controller_type: "keyboard", + button: button, + isTouch: true + }); + break; } return true; } @@ -206,7 +206,7 @@ export function isMobile(): boolean { let ret = false; (function (a) { // Check the user agent string against a regex for mobile devices - if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) { + if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) { ret = true; } })(navigator.userAgent || navigator.vendor || window["opera"]); diff --git a/src/ui-inputs.ts b/src/ui-inputs.ts index b9ecb55958c..92b1653df3d 100644 --- a/src/ui-inputs.ts +++ b/src/ui-inputs.ts @@ -1,11 +1,11 @@ import Phaser from "phaser"; -import {Mode} from "./ui/ui"; -import {InputsController} from "./inputs-controller"; +import { Mode } from "./ui/ui"; +import { InputsController } from "./inputs-controller"; import MessageUiHandler from "./ui/message-ui-handler"; import StarterSelectUiHandler from "./ui/starter-select-ui-handler"; -import {Setting, SettingKeys, settingIndex} from "./system/settings/settings"; +import { Setting, SettingKeys, settingIndex } from "./system/settings/settings"; import SettingsUiHandler from "./ui/settings/settings-ui-handler"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import SettingsGamepadUiHandler from "./ui/settings/settings-gamepad-ui-handler"; import SettingsKeyboardUiHandler from "#app/ui/settings/settings-keyboard-ui-handler"; import BattleScene from "./battle-scene"; @@ -142,7 +142,7 @@ export class UiInputs { } buttonGoToFilter(button: Button): void { - const whitelist = [StarterSelectUiHandler]; + const whitelist = [ StarterSelectUiHandler ]; const uiHandler = this.scene.ui?.getHandler(); if (whitelist.some(handler => uiHandler instanceof handler)) { this.scene.ui.processInput(button); @@ -168,31 +168,31 @@ export class UiInputs { return; } switch (this.scene.ui?.getMode()) { - case Mode.MESSAGE: - const messageHandler = this.scene.ui.getHandler(); - if (!messageHandler.pendingPrompt || messageHandler.isTextAnimationInProgress()) { + case Mode.MESSAGE: + const messageHandler = this.scene.ui.getHandler(); + if (!messageHandler.pendingPrompt || messageHandler.isTextAnimationInProgress()) { + return; + } + case Mode.TITLE: + case Mode.COMMAND: + case Mode.MODIFIER_SELECT: + case Mode.MYSTERY_ENCOUNTER: + this.scene.ui.setOverlayMode(Mode.MENU); + break; + case Mode.STARTER_SELECT: + this.buttonTouch(); + break; + case Mode.MENU: + this.scene.ui.revertMode(); + this.scene.playSound("ui/select"); + break; + default: return; - } - case Mode.TITLE: - case Mode.COMMAND: - case Mode.MODIFIER_SELECT: - case Mode.MYSTERY_ENCOUNTER: - this.scene.ui.setOverlayMode(Mode.MENU); - break; - case Mode.STARTER_SELECT: - this.buttonTouch(); - break; - case Mode.MENU: - this.scene.ui.revertMode(); - this.scene.playSound("ui/select"); - break; - default: - return; } } buttonCycleOption(button: Button): void { - const whitelist = [StarterSelectUiHandler, SettingsUiHandler, RunInfoUiHandler, SettingsDisplayUiHandler, SettingsAudioUiHandler, SettingsGamepadUiHandler, SettingsKeyboardUiHandler]; + const whitelist = [ StarterSelectUiHandler, SettingsUiHandler, RunInfoUiHandler, SettingsDisplayUiHandler, SettingsAudioUiHandler, SettingsGamepadUiHandler, SettingsKeyboardUiHandler ]; const uiHandler = this.scene.ui?.getHandler(); if (whitelist.some(handler => uiHandler instanceof handler)) { this.scene.ui.processInput(button); diff --git a/src/ui/abstact-option-select-ui-handler.ts b/src/ui/abstact-option-select-ui-handler.ts index 740830595ed..01fc5b00014 100644 --- a/src/ui/abstact-option-select-ui-handler.ts +++ b/src/ui/abstact-option-select-ui-handler.ts @@ -5,7 +5,7 @@ import UiHandler from "./ui-handler"; import { addWindow } from "./ui-theme"; import * as Utils from "../utils"; import { argbFromRgba } from "@material/material-color-utilities"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; export interface OptionSelectConfig { xOffset?: number; @@ -116,7 +116,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { this.optionSelectBg.height = this.getWindowHeight(); - this.optionSelectText.setPositionRelative(this.optionSelectBg, 12+24*this.scale, 2+42*this.scale); + this.optionSelectText.setPositionRelative(this.optionSelectBg, 12 + 24 * this.scale, 2 + 42 * this.scale); options.forEach((option: OptionSelectItem, i: integer) => { if (option.item) { @@ -165,6 +165,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { if (this.config.delay) { this.blockInput = true; this.optionSelectText.setAlpha(0.5); + this.cursorObj?.setAlpha(0.8); this.scene.time.delayedCall(Utils.fixedInt(this.config.delay), () => this.unblockInput()); } @@ -221,20 +222,20 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { } } else { switch (button) { - case Button.UP: - if (this.cursor) { - success = this.setCursor(this.cursor - 1); - } else if (this.cursor === 0) { - success = this.setCursor(options.length -1); - } - break; - case Button.DOWN: - if (this.cursor < options.length - 1) { - success = this.setCursor(this.cursor + 1); - } else { - success = this.setCursor(0); - } - break; + case Button.UP: + if (this.cursor) { + success = this.setCursor(this.cursor - 1); + } else if (this.cursor === 0) { + success = this.setCursor(options.length - 1); + } + break; + case Button.DOWN: + if (this.cursor < options.length - 1) { + success = this.setCursor(this.cursor + 1); + } else { + success = this.setCursor(0); + } + break; } if (this.config?.supportHover) { // handle hover code if the element supports hover-handlers and the option has the optional hover-handler set. @@ -256,6 +257,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { this.blockInput = false; this.optionSelectText.setAlpha(1); + this.cursorObj?.setAlpha(1); } getOptionsWithScroll(): OptionSelectItem[] { @@ -335,7 +337,7 @@ export default abstract class AbstractOptionSelectUiHandler extends UiHandler { } this.cursorObj.setScale(this.scale * 6); - this.cursorObj.setPositionRelative(this.optionSelectBg, 12, 102*this.scale + this.cursor * (114 * this.scale - 3)); + this.cursorObj.setPositionRelative(this.optionSelectBg, 12, 102 * this.scale + this.cursor * (114 * this.scale - 3)); return changed; } diff --git a/src/ui/achvs-ui-handler.ts b/src/ui/achvs-ui-handler.ts index 491c4acb523..a1ced6145eb 100644 --- a/src/ui/achvs-ui-handler.ts +++ b/src/ui/achvs-ui-handler.ts @@ -40,7 +40,9 @@ export default class AchvsUiHandler extends MessageUiHandler { private iconsBg: Phaser.GameObjects.NineSlice; private icons: Phaser.GameObjects.Sprite[]; + private titleBg: Phaser.GameObjects.NineSlice; private titleText: Phaser.GameObjects.Text; + private scoreContainer: Phaser.GameObjects.Container; private scoreText: Phaser.GameObjects.Text; private unlockText: Phaser.GameObjects.Text; @@ -79,7 +81,7 @@ export default class AchvsUiHandler extends MessageUiHandler { this.headerActionButton = new Phaser.GameObjects.Sprite(this.scene, 0, 0, "keyboard", "ACTION.png"); this.headerActionButton.setOrigin(0, 0); this.headerActionButton.setPositionRelative(this.headerBg, 236, 6); - this.headerActionText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW, {fontSize:"60px"}); + this.headerActionText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW, { fontSize:"60px" }); this.headerActionText.setOrigin(0, 0); this.headerActionText.setPositionRelative(this.headerBg, 264, 8); @@ -114,29 +116,31 @@ export default class AchvsUiHandler extends MessageUiHandler { const titleBg = addWindow(this.scene, 0, this.headerBg.height + this.iconsBg.height, 174, 24); titleBg.setOrigin(0, 0); + this.titleBg = titleBg; this.titleText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW); const textSize = languageSettings[i18next.language]?.TextSize ?? this.titleText.style.fontSize; this.titleText.setFontSize(textSize); - this.titleText.setOrigin(0, 0); const titleBgCenterX = titleBg.x + titleBg.width / 2; const titleBgCenterY = titleBg.y + titleBg.height / 2; this.titleText.setOrigin(0.5, 0.5); this.titleText.setPosition(titleBgCenterX, titleBgCenterY); - const scoreBg = addWindow(this.scene, titleBg.x + titleBg.width, titleBg.y, 46, 24); + this.scoreContainer = this.scene.add.container(titleBg.x + titleBg.width, titleBg.y); + const scoreBg = addWindow(this.scene, 0, 0, 46, 24); scoreBg.setOrigin(0, 0); + this.scoreContainer.add(scoreBg); - this.scoreText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW); - this.scoreText.setOrigin(0, 0); - this.scoreText.setPositionRelative(scoreBg, 8, 4); + this.scoreText = addTextObject(this.scene, scoreBg.width / 2, scoreBg.height / 2, "", TextStyle.WINDOW); + this.scoreText.setOrigin(0.5, 0.5); + this.scoreContainer.add(this.scoreText); - const unlockBg = addWindow(this.scene, scoreBg.x + scoreBg.width, scoreBg.y, 98, 24); + const unlockBg = addWindow(this.scene, this.scoreContainer.x + scoreBg.width, titleBg.y, 98, 24); unlockBg.setOrigin(0, 0); this.unlockText = addTextObject(this.scene, 0, 0, "", TextStyle.WINDOW); - this.unlockText.setOrigin(0, 0); - this.unlockText.setPositionRelative(unlockBg, 8, 4); + this.unlockText.setOrigin(0.5, 0.5); + this.unlockText.setPositionRelative(unlockBg, unlockBg.width / 2, unlockBg.height / 2); const descriptionBg = addWindow(this.scene, 0, titleBg.y + titleBg.height, (this.scene.game.canvas.width / 6) - 2, 42); descriptionBg.setOrigin(0, 0); @@ -157,8 +161,7 @@ export default class AchvsUiHandler extends MessageUiHandler { this.mainContainer.add(this.iconsContainer); this.mainContainer.add(titleBg); this.mainContainer.add(this.titleText); - this.mainContainer.add(scoreBg); - this.mainContainer.add(this.scoreText); + this.mainContainer.add(this.scoreContainer); this.mainContainer.add(unlockBg); this.mainContainer.add(this.unlockText); this.mainContainer.add(descriptionBg); @@ -167,8 +170,6 @@ export default class AchvsUiHandler extends MessageUiHandler { ui.add(this.mainContainer); this.currentPage = Page.ACHIEVEMENTS; - this.setCursor(0); - this.setScrollCursor(0); this.mainContainer.setVisible(false); } @@ -244,51 +245,51 @@ export default class AchvsUiHandler extends MessageUiHandler { const rowIndex = Math.floor(this.cursor / this.COLS); const itemOffset = (this.scrollCursor * this.COLS); switch (button) { - case Button.UP: - if (this.cursor < this.COLS) { - if (this.scrollCursor) { - success = this.setScrollCursor(this.scrollCursor - 1); - } else { + case Button.UP: + if (this.cursor < this.COLS) { + if (this.scrollCursor) { + success = this.setScrollCursor(this.scrollCursor - 1); + } else { // Wrap around to the last row - success = this.setScrollCursor(Math.ceil(this.currentTotal / this.COLS) - this.ROWS); - let newCursorIndex = this.cursor + (this.ROWS - 1) * this.COLS; - if (newCursorIndex > this.currentTotal - this.scrollCursor * this.COLS -1) { - newCursorIndex -= this.COLS; + success = this.setScrollCursor(Math.ceil(this.currentTotal / this.COLS) - this.ROWS); + let newCursorIndex = this.cursor + (this.ROWS - 1) * this.COLS; + if (newCursorIndex > this.currentTotal - this.scrollCursor * this.COLS - 1) { + newCursorIndex -= this.COLS; + } + success = success && this.setCursor(newCursorIndex); } - success = success && this.setCursor(newCursorIndex); - } - } else { - success = this.setCursor(this.cursor - this.COLS); - } - break; - case Button.DOWN: - const canMoveDown = itemOffset + 1 < this.currentTotal; - if (rowIndex >= this.ROWS - 1) { - if (this.scrollCursor < Math.ceil(this.currentTotal / this.COLS) - this.ROWS && canMoveDown) { - // scroll down one row - success = this.setScrollCursor(this.scrollCursor + 1); } else { - // wrap back to the first row - success = this.setScrollCursor(0) && this.setCursor(this.cursor % this.COLS); + success = this.setCursor(this.cursor - this.COLS); } - } else if (canMoveDown) { - success = this.setCursor(Math.min(this.cursor + this.COLS, this.currentTotal - itemOffset - 1)); - } - break; - case Button.LEFT: - if (this.cursor % this.COLS === 0) { - success = this.setCursor(Math.min(this.cursor + this.COLS - 1, this.currentTotal - itemOffset - 1)); - } else { - success = this.setCursor(this.cursor - 1); - } - break; - case Button.RIGHT: - if ((this.cursor + 1) % this.COLS === 0 || (this.cursor + itemOffset) === (this.currentTotal - 1)) { - success = this.setCursor(this.cursor - this.cursor % this.COLS); - } else { - success = this.setCursor(this.cursor + 1); - } - break; + break; + case Button.DOWN: + const canMoveDown = itemOffset + 1 < this.currentTotal; + if (rowIndex >= this.ROWS - 1) { + if (this.scrollCursor < Math.ceil(this.currentTotal / this.COLS) - this.ROWS && canMoveDown) { + // scroll down one row + success = this.setScrollCursor(this.scrollCursor + 1); + } else { + // wrap back to the first row + success = this.setScrollCursor(0) && this.setCursor(this.cursor % this.COLS); + } + } else if (canMoveDown) { + success = this.setCursor(Math.min(this.cursor + this.COLS, this.currentTotal - itemOffset - 1)); + } + break; + case Button.LEFT: + if (this.cursor % this.COLS === 0) { + success = this.setCursor(Math.min(this.cursor + this.COLS - 1, this.currentTotal - itemOffset - 1)); + } else { + success = this.setCursor(this.cursor - 1); + } + break; + case Button.RIGHT: + if ((this.cursor + 1) % this.COLS === 0 || (this.cursor + itemOffset) === (this.currentTotal - 1)) { + success = this.setCursor(this.cursor - this.cursor % this.COLS); + } else { + success = this.setCursor(this.cursor + 1); + } + break; } } @@ -315,12 +316,22 @@ export default class AchvsUiHandler extends MessageUiHandler { if (update || pageChange) { switch (this.currentPage) { - case Page.ACHIEVEMENTS: - this.showAchv(achvs[Object.keys(achvs)[cursor + this.scrollCursor * this.COLS]]); - break; - case Page.VOUCHERS: - this.showVoucher(vouchers[Object.keys(vouchers)[cursor + this.scrollCursor * this.COLS]]); - break; + case Page.ACHIEVEMENTS: + if (pageChange) { + this.titleBg.width = 174; + this.titleText.x = this.titleBg.width / 2; + this.scoreContainer.setVisible(true); + } + this.showAchv(achvs[Object.keys(achvs)[cursor + this.scrollCursor * this.COLS]]); + break; + case Page.VOUCHERS: + if (pageChange) { + this.titleBg.width = 220; + this.titleText.x = this.titleBg.width / 2; + this.scoreContainer.setVisible(false); + } + this.showVoucher(vouchers[Object.keys(vouchers)[cursor + this.scrollCursor * this.COLS]]); + break; } } return ret; @@ -347,14 +358,14 @@ export default class AchvsUiHandler extends MessageUiHandler { } switch (this.currentPage) { - case Page.ACHIEVEMENTS: - this.updateAchvIcons(); - this.showAchv(achvs[Object.keys(achvs)[this.cursor + this.scrollCursor * this.COLS]]); - break; - case Page.VOUCHERS: - this.updateVoucherIcons(); - this.showVoucher(vouchers[Object.keys(vouchers)[this.cursor + this.scrollCursor * this.COLS]]); - break; + case Page.ACHIEVEMENTS: + this.updateAchvIcons(); + this.showAchv(achvs[Object.keys(achvs)[this.cursor + this.scrollCursor * this.COLS]]); + break; + case Page.VOUCHERS: + this.updateVoucherIcons(); + this.showVoucher(vouchers[Object.keys(vouchers)[this.cursor + this.scrollCursor * this.COLS]]); + break; } return true; } @@ -442,6 +453,7 @@ export default class AchvsUiHandler extends MessageUiHandler { this.currentPage = Page.ACHIEVEMENTS; this.mainContainer.setVisible(false); this.setScrollCursor(0); + this.setCursor(0, true); this.eraseCursor(); } diff --git a/src/ui/admin-ui-handler.ts b/src/ui/admin-ui-handler.ts index c48138853fc..c73c02e66c2 100644 --- a/src/ui/admin-ui-handler.ts +++ b/src/ui/admin-ui-handler.ts @@ -20,7 +20,7 @@ export default class AdminUiHandler extends FormModalUiHandler { } getFields(config?: ModalConfig): string[] { - return ["Username", "Discord ID"]; + return [ "Username", "Discord ID" ]; } getWidth(config?: ModalConfig): number { @@ -28,11 +28,11 @@ export default class AdminUiHandler extends FormModalUiHandler { } getMargin(config?: ModalConfig): [number, number, number, number] { - return [0, 0, 48, 0]; + return [ 0, 0, 48, 0 ]; } getButtonLabels(config?: ModalConfig): string[] { - return ["Link account", "Cancel"]; + return [ "Link account", "Cancel" ]; } processInput(button: Button): boolean { @@ -50,7 +50,7 @@ export default class AdminUiHandler extends FormModalUiHandler { const originalSubmitAction = this.submitAction; this.submitAction = (_) => { this.submitAction = originalSubmitAction; - this.scene.ui.setMode(Mode.LOADING, { buttonActions: [] }); + this.scene.ui.setMode(Mode.LOADING, { buttonActions: []}); const onFail = error => { this.scene.ui.setMode(Mode.ADMIN, Object.assign(config, { errorMessage: error?.trim() })); this.scene.ui.playError(); diff --git a/src/ui/arena-flyout.ts b/src/ui/arena-flyout.ts index 42a2396e665..a82f97244cd 100644 --- a/src/ui/arena-flyout.ts +++ b/src/ui/arena-flyout.ts @@ -9,7 +9,7 @@ import { BattleSceneEventType, TurnEndEvent } from "../events/battle-scene"; import { ArenaTagType } from "#enums/arena-tag-type"; import TimeOfDayWidget from "./time-of-day-widget"; import * as Utils from "../utils"; -import i18next, {ParseKeys} from "i18next"; +import i18next, { ParseKeys } from "i18next"; /** Enum used to differentiate {@linkcode Arena} effects */ enum ArenaEffectType { @@ -196,7 +196,6 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { } - /** Clears out the current string stored in all arena effect texts */ private clearText() { this.flyoutTextPlayer.text = ""; @@ -216,20 +215,20 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { // Creates a proxy object to decide which text object needs to be updated let textObject: Phaser.GameObjects.Text; switch (fieldEffectInfo.effecType) { - case ArenaEffectType.PLAYER: - textObject = this.flyoutTextPlayer; - break; + case ArenaEffectType.PLAYER: + textObject = this.flyoutTextPlayer; + break; - case ArenaEffectType.WEATHER: - case ArenaEffectType.TERRAIN: - case ArenaEffectType.FIELD: - textObject = this.flyoutTextField; + case ArenaEffectType.WEATHER: + case ArenaEffectType.TERRAIN: + case ArenaEffectType.FIELD: + textObject = this.flyoutTextField; - break; + break; - case ArenaEffectType.ENEMY: - textObject = this.flyoutTextEnemy; - break; + case ArenaEffectType.ENEMY: + textObject = this.flyoutTextEnemy; + break; } textObject.text += fieldEffectInfo.name; @@ -254,81 +253,81 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { let foundIndex: number; switch (arenaEffectChangedEvent.constructor) { - case TagAddedEvent: - const tagAddedEvent = arenaEffectChangedEvent as TagAddedEvent; - const isArenaTrapTag = this.battleScene.arena.getTag(tagAddedEvent.arenaTagType) instanceof ArenaTrapTag; - let arenaEffectType: ArenaEffectType; + case TagAddedEvent: + const tagAddedEvent = arenaEffectChangedEvent as TagAddedEvent; + const isArenaTrapTag = this.battleScene.arena.getTag(tagAddedEvent.arenaTagType) instanceof ArenaTrapTag; + let arenaEffectType: ArenaEffectType; - if (tagAddedEvent.arenaTagSide === ArenaTagSide.BOTH) { - arenaEffectType = ArenaEffectType.FIELD; - } else if (tagAddedEvent.arenaTagSide === ArenaTagSide.PLAYER) { - arenaEffectType = ArenaEffectType.PLAYER; - } else { - arenaEffectType = ArenaEffectType.ENEMY; - } - - const existingTrapTagIndex = isArenaTrapTag ? this.fieldEffectInfo.findIndex(e => tagAddedEvent.arenaTagType === e.tagType && arenaEffectType === e.effecType) : -1; - let name: string = getFieldEffectText(ArenaTagType[tagAddedEvent.arenaTagType]); - - if (isArenaTrapTag) { - if (existingTrapTagIndex !== -1) { - const layers = tagAddedEvent.arenaTagMaxLayers > 1 ? ` (${tagAddedEvent.arenaTagLayers})` : ""; - this.fieldEffectInfo[existingTrapTagIndex].name = `${name}${layers}`; - break; - } else if (tagAddedEvent.arenaTagMaxLayers > 1) { - name = `${name} (${tagAddedEvent.arenaTagLayers})`; + if (tagAddedEvent.arenaTagSide === ArenaTagSide.BOTH) { + arenaEffectType = ArenaEffectType.FIELD; + } else if (tagAddedEvent.arenaTagSide === ArenaTagSide.PLAYER) { + arenaEffectType = ArenaEffectType.PLAYER; + } else { + arenaEffectType = ArenaEffectType.ENEMY; } - } - this.fieldEffectInfo.push({ - name, - effecType: arenaEffectType, - maxDuration: tagAddedEvent.duration, - duration: tagAddedEvent.duration, - tagType: tagAddedEvent.arenaTagType - }); - break; - case TagRemovedEvent: - const tagRemovedEvent = arenaEffectChangedEvent as TagRemovedEvent; - foundIndex = this.fieldEffectInfo.findIndex(info => info.tagType === tagRemovedEvent.arenaTagType); + const existingTrapTagIndex = isArenaTrapTag ? this.fieldEffectInfo.findIndex(e => tagAddedEvent.arenaTagType === e.tagType && arenaEffectType === e.effecType) : -1; + let name: string = getFieldEffectText(ArenaTagType[tagAddedEvent.arenaTagType]); - if (foundIndex !== -1) { // If the tag was being tracked, remove it - this.fieldEffectInfo.splice(foundIndex, 1); - } - break; + if (isArenaTrapTag) { + if (existingTrapTagIndex !== -1) { + const layers = tagAddedEvent.arenaTagMaxLayers > 1 ? ` (${tagAddedEvent.arenaTagLayers})` : ""; + this.fieldEffectInfo[existingTrapTagIndex].name = `${name}${layers}`; + break; + } else if (tagAddedEvent.arenaTagMaxLayers > 1) { + name = `${name} (${tagAddedEvent.arenaTagLayers})`; + } + } - case WeatherChangedEvent: - case TerrainChangedEvent: - const fieldEffectChangedEvent = arenaEffectChangedEvent as WeatherChangedEvent | TerrainChangedEvent; + this.fieldEffectInfo.push({ + name, + effecType: arenaEffectType, + maxDuration: tagAddedEvent.duration, + duration: tagAddedEvent.duration, + tagType: tagAddedEvent.arenaTagType + }); + break; + case TagRemovedEvent: + const tagRemovedEvent = arenaEffectChangedEvent as TagRemovedEvent; + foundIndex = this.fieldEffectInfo.findIndex(info => info.tagType === tagRemovedEvent.arenaTagType); - // Stores the old Weather/Terrain name in case it's in the array already - const oldName = + if (foundIndex !== -1) { // If the tag was being tracked, remove it + this.fieldEffectInfo.splice(foundIndex, 1); + } + break; + + case WeatherChangedEvent: + case TerrainChangedEvent: + const fieldEffectChangedEvent = arenaEffectChangedEvent as WeatherChangedEvent | TerrainChangedEvent; + + // Stores the old Weather/Terrain name in case it's in the array already + const oldName = getFieldEffectText(fieldEffectChangedEvent instanceof WeatherChangedEvent ? WeatherType[fieldEffectChangedEvent.oldWeatherType] : TerrainType[fieldEffectChangedEvent.oldTerrainType]); - // Stores the new Weather/Terrain info - const newInfo = { - name: + // Stores the new Weather/Terrain info + const newInfo = { + name: getFieldEffectText(fieldEffectChangedEvent instanceof WeatherChangedEvent ? WeatherType[fieldEffectChangedEvent.newWeatherType] : TerrainType[fieldEffectChangedEvent.newTerrainType]), - effecType: fieldEffectChangedEvent instanceof WeatherChangedEvent - ? ArenaEffectType.WEATHER - : ArenaEffectType.TERRAIN, - maxDuration: fieldEffectChangedEvent.duration, - duration: fieldEffectChangedEvent.duration}; + effecType: fieldEffectChangedEvent instanceof WeatherChangedEvent + ? ArenaEffectType.WEATHER + : ArenaEffectType.TERRAIN, + maxDuration: fieldEffectChangedEvent.duration, + duration: fieldEffectChangedEvent.duration }; - foundIndex = this.fieldEffectInfo.findIndex(info => [newInfo.name, oldName].includes(info.name)); - if (foundIndex === -1) { - if (newInfo.name !== undefined) { - this.fieldEffectInfo.push(newInfo); // Adds the info to the array if it doesn't already exist and is defined + foundIndex = this.fieldEffectInfo.findIndex(info => [ newInfo.name, oldName ].includes(info.name)); + if (foundIndex === -1) { + if (newInfo.name !== undefined) { + this.fieldEffectInfo.push(newInfo); // Adds the info to the array if it doesn't already exist and is defined + } + } else if (!newInfo.name) { + this.fieldEffectInfo.splice(foundIndex, 1); // Removes the old info if the new one is undefined + } else { + this.fieldEffectInfo[foundIndex] = newInfo; // Otherwise, replace the old info } - } else if (!newInfo.name) { - this.fieldEffectInfo.splice(foundIndex, 1); // Removes the old info if the new one is undefined - } else { - this.fieldEffectInfo[foundIndex] = newInfo; // Otherwise, replace the old info - } - break; + break; } this.updateFieldText(); diff --git a/src/ui/awaitable-ui-handler.ts b/src/ui/awaitable-ui-handler.ts index c6dc717aa3a..8256f938106 100644 --- a/src/ui/awaitable-ui-handler.ts +++ b/src/ui/awaitable-ui-handler.ts @@ -1,7 +1,7 @@ import BattleScene from "../battle-scene"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; export default abstract class AwaitableUiHandler extends UiHandler { protected awaitingActionInput: boolean; diff --git a/src/ui/ball-ui-handler.ts b/src/ui/ball-ui-handler.ts index 332fe5f65b9..9df6da36055 100644 --- a/src/ui/ball-ui-handler.ts +++ b/src/ui/ball-ui-handler.ts @@ -5,7 +5,7 @@ import { Command } from "./command-ui-handler"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import { addWindow } from "./ui-theme"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import { CommandPhase } from "#app/phases/command-phase"; export default class BallUiHandler extends UiHandler { @@ -90,12 +90,12 @@ export default class BallUiHandler extends UiHandler { } } else { switch (button) { - case Button.UP: - success = this.setCursor(this.cursor ? this.cursor - 1 : pokeballTypeCount); - break; - case Button.DOWN: - success = this.setCursor(this.cursor < pokeballTypeCount ? this.cursor + 1 : 0); - break; + case Button.UP: + success = this.setCursor(this.cursor ? this.cursor - 1 : pokeballTypeCount); + break; + case Button.DOWN: + success = this.setCursor(this.cursor < pokeballTypeCount ? this.cursor + 1 : 0); + break; } } diff --git a/src/ui/battle-flyout.ts b/src/ui/battle-flyout.ts index fe561b76c9f..4541a2bfefa 100644 --- a/src/ui/battle-flyout.ts +++ b/src/ui/battle-flyout.ts @@ -149,7 +149,7 @@ export default class BattleFlyout extends Phaser.GameObjects.Container { if (foundInfo) { foundInfo.ppUsed = moveUsedEvent.ppUsed; } else { - this.moveInfo.push({move: moveUsedEvent.move, maxPp: moveUsedEvent.move.pp, ppUsed: moveUsedEvent.ppUsed}); + this.moveInfo.push({ move: moveUsedEvent.move, maxPp: moveUsedEvent.move.pp, ppUsed: moveUsedEvent.ppUsed }); } this.setText(); diff --git a/src/ui/battle-info.ts b/src/ui/battle-info.ts index b3474bed5cd..1d97998f491 100644 --- a/src/ui/battle-info.ts +++ b/src/ui/battle-info.ts @@ -326,7 +326,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { this.teraIcon.setVisible(this.lastTeraType !== Type.UNKNOWN); this.teraIcon.on("pointerover", () => { if (this.lastTeraType !== Type.UNKNOWN) { - (this.scene as BattleScene).ui.showTooltip("", i18next.t("fightUiHandler:teraHover", {type: i18next.t(`pokemonInfo:Type.${Type[this.lastTeraType]}`) })); + (this.scene as BattleScene).ui.showTooltip("", i18next.t("fightUiHandler:teraHover", { type: i18next.t(`pokemonInfo:Type.${Type[this.lastTeraType]}`) })); } }); this.teraIcon.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip()); @@ -593,7 +593,7 @@ export default class BattleInfo extends Phaser.GameObjects.Container { }; const updatePokemonHp = () => { - let duration = !instant ? Utils.clampInt(Math.abs((this.lastHp) - pokemon.hp) * 5, 250, 5000) : 0; + let duration = !instant ? Phaser.Math.Clamp(Math.abs((this.lastHp) - pokemon.hp) * 5, 250, 5000) : 0; const speed = (this.scene as BattleScene).hpBarSpeed; if (speed) { duration = speed >= 3 ? 0 : duration / Math.pow(2, speed); diff --git a/src/ui/battle-message-ui-handler.ts b/src/ui/battle-message-ui-handler.ts index c27c6974192..832d665b290 100644 --- a/src/ui/battle-message-ui-handler.ts +++ b/src/ui/battle-message-ui-handler.ts @@ -4,7 +4,7 @@ import { Mode } from "./ui"; import MessageUiHandler from "./message-ui-handler"; import { addWindow } from "./ui-theme"; import BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import i18next from "i18next"; import { Stat, PERMANENT_STATS, getStatKey } from "#app/enums/stat"; @@ -55,7 +55,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler { moveDetailsWindow.setName("move-details-window"); moveDetailsWindow.setOrigin(0, 1); - this.movesWindowContainer.add([movesWindow, moveDetailsWindow]); + this.movesWindowContainer.add([ movesWindow, moveDetailsWindow ]); ui.add(this.movesWindowContainer); const messageContainer = this.scene.add.container(12, -39); @@ -113,7 +113,7 @@ export default class BattleMessageUiHandler extends MessageUiHandler { this.levelUpStatsIncrContent = levelUpStatsIncrContent; - const levelUpStatsValuesContent = addBBCodeTextObject(this.scene, (this.scene.game.canvas.width / 6) - 7, -94, "", TextStyle.WINDOW, { maxLines: 6, lineSpacing: 5}); + const levelUpStatsValuesContent = addBBCodeTextObject(this.scene, (this.scene.game.canvas.width / 6) - 7, -94, "", TextStyle.WINDOW, { maxLines: 6, lineSpacing: 5 }); levelUpStatsValuesContent.setLineSpacing(i18next.resolvedLanguage === "ja" ? 25 : 5); levelUpStatsValuesContent.setOrigin(1, 0); levelUpStatsValuesContent.setAlign("right"); diff --git a/src/ui/bgm-bar.ts b/src/ui/bgm-bar.ts index 936ab91d8fa..616b3ff87cf 100644 --- a/src/ui/bgm-bar.ts +++ b/src/ui/bgm-bar.ts @@ -1,5 +1,5 @@ import BattleScene from "../battle-scene"; -import {addTextObject, TextStyle} from "./text"; +import { addTextObject, TextStyle } from "./text"; import i18next from "i18next"; import * as Utils from "#app/utils"; @@ -88,6 +88,6 @@ export default class BgmBar extends Phaser.GameObjects.Container { } getRealBgmName(bgmName: string): string { - return i18next.t([`bgmName:${bgmName}`, "bgmName:missing_entries"], {name: Utils.formatText(bgmName)}); + return i18next.t([ `bgmName:${bgmName}`, "bgmName:missing_entries" ], { name: Utils.formatText(bgmName) }); } } diff --git a/src/ui/challenges-select-ui-handler.ts b/src/ui/challenges-select-ui-handler.ts index 924186de789..e2547a626de 100644 --- a/src/ui/challenges-select-ui-handler.ts +++ b/src/ui/challenges-select-ui-handler.ts @@ -3,7 +3,7 @@ import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import { addWindow } from "./ui-theme"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import i18next from "i18next"; import { Challenge } from "#app/data/challenge"; import * as Utils from "../utils"; @@ -110,7 +110,7 @@ export default class GameChallengesUiHandler extends UiHandler { }); this.descriptionText.setName("text-desc"); this.scene.add.existing(this.descriptionText); - this.descriptionText.setScale(1/6); + this.descriptionText.setScale(1 / 6); this.descriptionText.setShadow(4, 5, ShadowColor.ORANGE); this.descriptionText.setOrigin(0, 0); @@ -376,66 +376,66 @@ export default class GameChallengesUiHandler extends UiHandler { } else { if (this.cursorObj?.visible && !this.startCursor.visible) { switch (button) { - case Button.UP: - if (this.cursor === 0) { - if (this.scrollCursor === 0) { + case Button.UP: + if (this.cursor === 0) { + if (this.scrollCursor === 0) { // When at the top of the menu and pressing UP, move to the bottommost item. - if (this.scene.gameMode.challenges.length > rowsToDisplay) { // If there are more than 9 challenges, scroll to the bottom + if (this.scene.gameMode.challenges.length > rowsToDisplay) { // If there are more than 9 challenges, scroll to the bottom // First, set the cursor to the last visible element, preparing for the scroll to the end. - const successA = this.setCursor(rowsToDisplay - 1); - // Then, adjust the scroll to display the bottommost elements of the menu. - const successB = this.setScrollCursor(this.scene.gameMode.challenges.length - rowsToDisplay); - success = successA && successB; // success is just there to play the little validation sound effect - } else { // If there are 9 or less challenges, just move to the bottom one - success = this.setCursor(this.scene.gameMode.challenges.length - 1); + const successA = this.setCursor(rowsToDisplay - 1); + // Then, adjust the scroll to display the bottommost elements of the menu. + const successB = this.setScrollCursor(this.scene.gameMode.challenges.length - rowsToDisplay); + success = successA && successB; // success is just there to play the little validation sound effect + } else { // If there are 9 or less challenges, just move to the bottom one + success = this.setCursor(this.scene.gameMode.challenges.length - 1); + } + } else { + success = this.setScrollCursor(this.scrollCursor - 1); } } else { - success = this.setScrollCursor(this.scrollCursor - 1); + success = this.setCursor(this.cursor - 1); } - } else { - success = this.setCursor(this.cursor - 1); - } - if (success) { - this.updateText(); - } - break; - case Button.DOWN: - if (this.cursor === rowsToDisplay - 1) { - if (this.scrollCursor < this.scene.gameMode.challenges.length - rowsToDisplay) { + if (success) { + this.updateText(); + } + break; + case Button.DOWN: + if (this.cursor === rowsToDisplay - 1) { + if (this.scrollCursor < this.scene.gameMode.challenges.length - rowsToDisplay) { // When at the bottom and pressing DOWN, scroll if possible. - success = this.setScrollCursor(this.scrollCursor + 1); - } else { + success = this.setScrollCursor(this.scrollCursor + 1); + } else { // When at the bottom of a scrolling menu and pressing DOWN, move to the topmost item. // First, set the cursor to the first visible element, preparing for the scroll to the top. - const successA = this.setCursor(0); - // Then, adjust the scroll to display the topmost elements of the menu. - const successB = this.setScrollCursor(0); - success = successA && successB; // success is just there to play the little validation sound effect - } - } else if (this.scene.gameMode.challenges.length < rowsToDisplay && this.cursor === this.scene.gameMode.challenges.length - 1) { + const successA = this.setCursor(0); + // Then, adjust the scroll to display the topmost elements of the menu. + const successB = this.setScrollCursor(0); + success = successA && successB; // success is just there to play the little validation sound effect + } + } else if (this.scene.gameMode.challenges.length < rowsToDisplay && this.cursor === this.scene.gameMode.challenges.length - 1) { // When at the bottom of a non-scrolling menu and pressing DOWN, move to the topmost item. - success = this.setCursor(0); - } else { - success = this.setCursor(this.cursor + 1); - } - if (success) { - this.updateText(); - } - break; - case Button.LEFT: + success = this.setCursor(0); + } else { + success = this.setCursor(this.cursor + 1); + } + if (success) { + this.updateText(); + } + break; + case Button.LEFT: // Moves the option cursor left, if possible. - success = this.getActiveChallenge().decreaseValue(); - if (success) { - this.updateText(); - } - break; - case Button.RIGHT: + success = this.getActiveChallenge().decreaseValue(); + if (success) { + this.updateText(); + } + break; + case Button.RIGHT: // Moves the option cursor right, if possible. - success = this.getActiveChallenge().increaseValue(); - if (success) { - this.updateText(); - } - break; + success = this.getActiveChallenge().increaseValue(); + if (success) { + this.updateText(); + } + break; } } } diff --git a/src/ui/command-ui-handler.ts b/src/ui/command-ui-handler.ts index 764e71a8c3f..0f5edc28675 100644 --- a/src/ui/command-ui-handler.ts +++ b/src/ui/command-ui-handler.ts @@ -4,7 +4,7 @@ import PartyUiHandler, { PartyUiMode } from "./party-ui-handler"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import i18next from "i18next"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import { getPokemonNameWithAffix } from "#app/messages"; import { CommandPhase } from "#app/phases/command-phase"; @@ -67,7 +67,7 @@ export default class CommandUiHandler extends UiHandler { messageHandler.commandWindow.setVisible(true); messageHandler.movesWindowContainer.setVisible(false); messageHandler.message.setWordWrapWidth(1110); - messageHandler.showText(i18next.t("commandUiHandler:actionMessage", {pokemonName: getPokemonNameWithAffix(commandPhase.getPokemon())}), 0); + messageHandler.showText(i18next.t("commandUiHandler:actionMessage", { pokemonName: getPokemonNameWithAffix(commandPhase.getPokemon()) }), 0); if (this.getCursor() === Command.POKEMON) { this.setCursor(Command.FIGHT); } else { @@ -89,54 +89,54 @@ export default class CommandUiHandler extends UiHandler { if (button === Button.ACTION) { switch (cursor) { // Fight - case Command.FIGHT: - if ((this.scene.getCurrentPhase() as CommandPhase).checkFightOverride()) { - return true; - } - ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); - success = true; - break; + case Command.FIGHT: + if ((this.scene.getCurrentPhase() as CommandPhase).checkFightOverride()) { + return true; + } + ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex()); + success = true; + break; // Ball - case Command.BALL: - ui.setModeWithoutClear(Mode.BALL); - success = true; - break; + case Command.BALL: + ui.setModeWithoutClear(Mode.BALL); + success = true; + break; // Pokemon - case Command.POKEMON: - ui.setMode(Mode.PARTY, PartyUiMode.SWITCH, (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getFieldIndex(), null, PartyUiHandler.FilterNonFainted); - success = true; - break; + case Command.POKEMON: + ui.setMode(Mode.PARTY, PartyUiMode.SWITCH, (this.scene.getCurrentPhase() as CommandPhase).getPokemon().getFieldIndex(), null, PartyUiHandler.FilterNonFainted); + success = true; + break; // Run - case Command.RUN: - (this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.RUN, 0); - success = true; - break; + case Command.RUN: + (this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.RUN, 0); + success = true; + break; } } else { (this.scene.getCurrentPhase() as CommandPhase).cancel(); } } else { switch (button) { - case Button.UP: - if (cursor >= 2) { - success = this.setCursor(cursor - 2); - } - break; - case Button.DOWN: - if (cursor < 2) { - success = this.setCursor(cursor + 2); - } - break; - case Button.LEFT: - if (cursor % 2 === 1) { - success = this.setCursor(cursor - 1); - } - break; - case Button.RIGHT: - if (cursor % 2 === 0) { - success = this.setCursor(cursor + 1); - } - break; + case Button.UP: + if (cursor >= 2) { + success = this.setCursor(cursor - 2); + } + break; + case Button.DOWN: + if (cursor < 2) { + success = this.setCursor(cursor + 2); + } + break; + case Button.LEFT: + if (cursor % 2 === 1) { + success = this.setCursor(cursor - 1); + } + break; + case Button.RIGHT: + if (cursor % 2 === 0) { + success = this.setCursor(cursor + 1); + } + break; } } diff --git a/src/ui/confirm-ui-handler.ts b/src/ui/confirm-ui-handler.ts index 4a60b0c9689..2022508fc0d 100644 --- a/src/ui/confirm-ui-handler.ts +++ b/src/ui/confirm-ui-handler.ts @@ -2,7 +2,7 @@ import BattleScene from "../battle-scene"; import AbstractOptionSelectUiHandler, { OptionSelectConfig } from "./abstact-option-select-ui-handler"; import { Mode } from "./ui"; import i18next from "i18next"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { @@ -76,7 +76,8 @@ export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { } } ], - delay: args.length >= 6 && args[5] !== null ? args[5] as integer : 0 + delay: args.length >= 6 && args[5] !== null ? args[5] as number : 0, + noCancel: args.length >= 7 && args[6] !== null ? args[6] as boolean : false, }; super.show([ config ]); @@ -96,7 +97,7 @@ export default class ConfirmUiHandler extends AbstractOptionSelectUiHandler { } processInput(button: Button): boolean { - if (button === Button.CANCEL && this.blockInput) { + if (button === Button.CANCEL && this.blockInput && !this.config?.noCancel) { this.unblockInput(); } diff --git a/src/ui/daily-run-scoreboard.ts b/src/ui/daily-run-scoreboard.ts index b535a94d35c..b9c1c6ea49a 100644 --- a/src/ui/daily-run-scoreboard.ts +++ b/src/ui/daily-run-scoreboard.ts @@ -142,13 +142,13 @@ export class DailyRunScoreboard extends Phaser.GameObjects.Container { entryContainer.add(scoreLabel); switch (this.category) { - case ScoreboardCategory.DAILY: - const waveLabel = addTextObject(this.scene, 68, 0, wave, TextStyle.WINDOW, { fontSize: "54px" }); - entryContainer.add(waveLabel); - break; - case ScoreboardCategory.WEEKLY: - scoreLabel.x -= 16; - break; + case ScoreboardCategory.DAILY: + const waveLabel = addTextObject(this.scene, 68, 0, wave, TextStyle.WINDOW, { fontSize: "54px" }); + entryContainer.add(waveLabel); + break; + case ScoreboardCategory.WEEKLY: + scoreLabel.x -= 16; + break; } return entryContainer; diff --git a/src/ui/dropdown.ts b/src/ui/dropdown.ts index 4e1235c211d..e16efe17036 100644 --- a/src/ui/dropdown.ts +++ b/src/ui/dropdown.ts @@ -64,7 +64,7 @@ export class DropDownOption extends Phaser.GameObjects.Container { if (Array.isArray(labels)) { this.labels = labels; } else { - this.labels = labels? [ labels ] : [ new DropDownLabel("") ]; + this.labels = labels ? [ labels ] : [ new DropDownLabel("") ]; } this.currentLabelIndex = 0; const currentLabel = this.labels[this.currentLabelIndex]; @@ -75,12 +75,12 @@ export class DropDownOption extends Phaser.GameObjects.Container { this.add(this.text); // Add to container the sprite for each label if there is one - for (let i=0; i < this.labels.length; i++) { + for (let i = 0; i < this.labels.length; i++) { const sprite = this.labels[i].sprite; if (sprite) { this.add(sprite); sprite.setOrigin(0, 0.5); - if (i!== this.currentLabelIndex) { + if (i !== this.currentLabelIndex) { sprite.setVisible(false); } } @@ -115,18 +115,18 @@ export class DropDownOption extends Phaser.GameObjects.Container { */ private updateToggleIconColor(): void { switch (this.state) { - case DropDownState.ON: - this.toggle.setTint(this.onColor); - break; - case DropDownState.OFF: - this.toggle.setTint(this.offColor); - break; - case DropDownState.EXCLUDE: - this.toggle.setTint(this.excludeColor); - break; - case DropDownState.UNLOCKABLE: - this.toggle.setTint(this.unlockableColor); - break; + case DropDownState.ON: + this.toggle.setTint(this.onColor); + break; + case DropDownState.OFF: + this.toggle.setTint(this.offColor); + break; + case DropDownState.EXCLUDE: + this.toggle.setTint(this.excludeColor); + break; + case DropDownState.UNLOCKABLE: + this.toggle.setTint(this.unlockableColor); + break; } } @@ -215,7 +215,7 @@ export class DropDownOption extends Phaser.GameObjects.Container { */ setLabelPosition(x: number, y: number) { let textX = x; - for (let i=0; i < this.labels.length; i++) { + for (let i = 0; i < this.labels.length; i++) { const label = this.labels[i]; if (label.sprite) { label.sprite.x = x; @@ -261,7 +261,7 @@ export class DropDownOption extends Phaser.GameObjects.Container { const currentText = this.text.text; for (const label of this.labels) { this.text.setText(label.text); - const spriteWidth = label.sprite? label.sprite.displayWidth + 2 : 0; + const spriteWidth = label.sprite ? label.sprite.displayWidth + 2 : 0; w = Math.max(w, this.text.displayWidth + spriteWidth); } this.text.setText(currentText); @@ -334,7 +334,7 @@ export class DropDown extends Phaser.GameObjects.Container { } getWidth(): number { - return this.window? this.window.width : this.width; + return this.window ? this.window.width : this.width; } toggleVisibility(): void { @@ -460,7 +460,7 @@ export class DropDown extends Phaser.GameObjects.Container { return this.options.filter((_, i) => i > 0).map(option => option.val); } // if nothing is selected and a single option is hovered, return that one - return [this.options[this.cursor].val]; + return [ this.options[this.cursor].val ]; } else if (this.dropDownType === DropDownType.RADIAL) { return this.options.map((option) => { return { val: option.val, state: option.state }; @@ -500,18 +500,18 @@ export class DropDown extends Phaser.GameObjects.Container { }; switch (this.dropDownType) { - case DropDownType.MULTI: - case DropDownType.RADIAL: - return compareValues(["val", "state"]); + case DropDownType.MULTI: + case DropDownType.RADIAL: + return compareValues([ "val", "state" ]); - case DropDownType.HYBRID: - return compareValues(["val", "state", "cursor"]); + case DropDownType.HYBRID: + return compareValues([ "val", "state", "cursor" ]); - case DropDownType.SINGLE: - return compareValues(["val", "state", "dir"]); + case DropDownType.SINGLE: + return compareValues([ "val", "state", "dir" ]); - default: - return false; + default: + return false; } } diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index e8753122b6d..8f977ba2ac0 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -34,6 +34,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { private cursorObj: Phaser.GameObjects.Image; private transitioning: boolean; private transitionCancelled: boolean; + private summaryFinished: boolean; private defaultText: string; private scale: number = 0.1666666667; @@ -106,7 +107,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { let pokemonIconX = -20; let pokemonIconY = 6; - if (["de", "es", "fr", "ko", "pt-BR"].includes(currentLanguage)) { + if ([ "de", "es", "fr", "ko", "pt-BR" ].includes(currentLanguage)) { gachaTextStyle = TextStyle.SMALLER_WINDOW_ALT; gachaX = 2; gachaY = 2; @@ -114,7 +115,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { let legendaryLabelX = gachaX; let legendaryLabelY = gachaY; - if (["de", "es"].includes(currentLanguage)) { + if ([ "de", "es" ].includes(currentLanguage)) { pokemonIconX = -25; pokemonIconY = 10; legendaryLabelX = -6; @@ -126,47 +127,47 @@ export default class EggGachaUiHandler extends MessageUiHandler { gachaInfoContainer.add(gachaUpLabel); switch (gachaType as GachaType) { - case GachaType.LEGENDARY: - if (["de", "es"].includes(currentLanguage)) { - gachaUpLabel.setAlign("center"); - gachaUpLabel.setY(0); - } - if (["pt-BR"].includes(currentLanguage)) { - gachaUpLabel.setX(legendaryLabelX - 2); - } else { - gachaUpLabel.setX(legendaryLabelX); - } - gachaUpLabel.setY(legendaryLabelY); + case GachaType.LEGENDARY: + if ([ "de", "es" ].includes(currentLanguage)) { + gachaUpLabel.setAlign("center"); + gachaUpLabel.setY(0); + } + if ([ "pt-BR" ].includes(currentLanguage)) { + gachaUpLabel.setX(legendaryLabelX - 2); + } else { + gachaUpLabel.setX(legendaryLabelX); + } + gachaUpLabel.setY(legendaryLabelY); - const pokemonIcon = this.scene.add.sprite(pokemonIconX, pokemonIconY, "pokemon_icons_0"); - if (["pt-BR"].includes(currentLanguage)) { - pokemonIcon.setX(pokemonIconX - 2); - } - pokemonIcon.setScale(0.5); - pokemonIcon.setOrigin(0, 0.5); + const pokemonIcon = this.scene.add.sprite(pokemonIconX, pokemonIconY, "pokemon_icons_0"); + if ([ "pt-BR" ].includes(currentLanguage)) { + pokemonIcon.setX(pokemonIconX - 2); + } + pokemonIcon.setScale(0.5); + pokemonIcon.setOrigin(0, 0.5); - gachaInfoContainer.add(pokemonIcon); - break; - case GachaType.MOVE: - if (["de", "es", "fr", "pt-BR"].includes(currentLanguage)) { - gachaUpLabel.setAlign("center"); - gachaUpLabel.setY(0); - } + gachaInfoContainer.add(pokemonIcon); + break; + case GachaType.MOVE: + if ([ "de", "es", "fr", "pt-BR" ].includes(currentLanguage)) { + gachaUpLabel.setAlign("center"); + gachaUpLabel.setY(0); + } - gachaUpLabel.setText(i18next.t("egg:moveUPGacha")); - gachaUpLabel.setX(0); - gachaUpLabel.setOrigin(0.5, 0); - break; - case GachaType.SHINY: - if (["de", "fr", "ko"].includes(currentLanguage)) { - gachaUpLabel.setAlign("center"); - gachaUpLabel.setY(0); - } + gachaUpLabel.setText(i18next.t("egg:moveUPGacha")); + gachaUpLabel.setX(0); + gachaUpLabel.setOrigin(0.5, 0); + break; + case GachaType.SHINY: + if ([ "de", "fr", "ko" ].includes(currentLanguage)) { + gachaUpLabel.setAlign("center"); + gachaUpLabel.setY(0); + } - gachaUpLabel.setText(i18next.t("egg:shinyUPGacha")); - gachaUpLabel.setX(0); - gachaUpLabel.setOrigin(0.5, 0); - break; + gachaUpLabel.setText(i18next.t("egg:shinyUPGacha")); + gachaUpLabel.setX(0); + gachaUpLabel.setOrigin(0.5, 0); + break; } const gachaKnob = this.scene.add.sprite(191, 89, "gacha_knob"); @@ -221,7 +222,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { const pullOptionsText = pullOptions.map(option =>{ const desc = option.description.split(" "); if (desc[0].length < 2) { - desc[0] += ["zh", "ko"].includes(resolvedLanguage.substring(0, 2)) ? " " : " "; + desc[0] += [ "zh", "ko" ].includes(resolvedLanguage.substring(0, 2)) ? " " : " "; } if (option.multiplier === multiplierOne) { desc[0] = " " + desc[0]; @@ -469,17 +470,22 @@ export default class EggGachaUiHandler extends MessageUiHandler { getGuaranteedEggTierFromPullCount(pullCount: number): EggTier { switch (pullCount) { - case 10: - return EggTier.GREAT; - case 25: - return EggTier.ULTRA; - default: - return EggTier.COMMON; + case 10: + return EggTier.RARE; + case 25: + return EggTier.EPIC; + default: + return EggTier.COMMON; } } showSummary(eggs: Egg[]): void { - this.transitioning = false; + // the overlay will appear faster if the egg pulling animation was skipped + const overlayEaseInDuration = this.getDelayValue(750); + + this.summaryFinished = false; + this.transitionCancelled = false; + this.setTransitioning(true); this.eggGachaSummaryContainer.setVisible(true); const eggScale = eggs.length < 20 ? 1 : 0.5; @@ -488,12 +494,14 @@ export default class EggGachaUiHandler extends MessageUiHandler { targets: this.eggGachaOverlay, alpha: 0.5, ease: "Sine.easeOut", - duration: 750, + duration: overlayEaseInDuration, onComplete: () => { const rowItems = 5; const rows = Math.ceil(eggs.length / rowItems); const cols = Math.min(eggs.length, rowItems); const height = this.eggGachaOverlay.displayHeight - this.eggGachaMessageBox.displayHeight; + + // Create sprites for each egg const eggContainers = eggs.map((egg, t) => { const col = t % rowItems; const row = Math.floor(t / rowItems); @@ -508,21 +516,31 @@ export default class EggGachaUiHandler extends MessageUiHandler { const eggText = addTextObject(this.scene, 0, 14, egg.getEggDescriptor(), TextStyle.PARTY, { align: "center" }); eggText.setOrigin(0.5, 0); - eggText.setTint(getEggTierTextTint(!egg.isManaphyEgg() ? egg.tier : EggTier.ULTRA)); + eggText.setTint(getEggTierTextTint(!egg.isManaphyEgg() ? egg.tier : EggTier.EPIC)); ret.add(eggText); this.eggGachaSummaryContainer.addAt(ret, 0); return ret; }); - eggContainers.forEach((eggContainer, e) => { - this.scene.tweens.add({ - targets: eggContainer, - delay: this.getDelayValue(e * 100), - duration: this.getDelayValue(350), - scale: eggScale, - ease: "Sine.easeOut" - }); + // If action/cancel was pressed when the overlay was easing in, show all eggs at once + // Otherwise show the eggs one by one with a small delay between each + eggContainers.forEach((eggContainer, index) => { + const delay = !this.transitionCancelled ? this.getDelayValue(index * 100) : 0; + this.scene.time.delayedCall(delay, () => + this.scene.tweens.add({ + targets: eggContainer, + duration: this.getDelayValue(350), + scale: eggScale, + ease: "Sine.easeOut", + onComplete: () => { + if (index === eggs.length - 1) { + this.setTransitioning(false); + this.summaryFinished = true; + } + } + })); + }); } }); @@ -540,6 +558,7 @@ export default class EggGachaUiHandler extends MessageUiHandler { this.eggGachaSummaryContainer.setAlpha(1); this.eggGachaSummaryContainer.removeAll(true); this.setTransitioning(false); + this.summaryFinished = false; this.eggGachaOptionsContainer.setVisible(true); } }); @@ -548,11 +567,11 @@ export default class EggGachaUiHandler extends MessageUiHandler { updateGachaInfo(gachaType: GachaType): void { const infoContainer = this.gachaInfoContainers[gachaType]; switch (gachaType as GachaType) { - case GachaType.LEGENDARY: - const species = getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(this.scene, new Date().getTime())); - const pokemonIcon = infoContainer.getAt(1) as Phaser.GameObjects.Sprite; - pokemonIcon.setTexture(species.getIconAtlasKey(), species.getIconId(false)); - break; + case GachaType.LEGENDARY: + const species = getPokemonSpecies(getLegendaryGachaSpeciesForTimestamp(this.scene, new Date().getTime())); + const pokemonIcon = infoContainer.getAt(1) as Phaser.GameObjects.Sprite; + pokemonIcon.setTexture(species.getIconAtlasKey(), species.getIconId(false)); + break; } } @@ -613,112 +632,112 @@ export default class EggGachaUiHandler extends MessageUiHandler { } else { if (this.eggGachaSummaryContainer.visible) { - if (button === Button.ACTION || button === Button.CANCEL) { + if (this.summaryFinished && (button === Button.ACTION || button === Button.CANCEL)) { this.hideSummary(); success = true; } } else { switch (button) { - case Button.ACTION: - switch (this.cursor) { - case 0: - if (!this.scene.gameData.voucherCounts[VoucherType.REGULAR] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { - error = true; - this.showError(i18next.t("egg:notEnoughVouchers")); - } else if (this.scene.gameData.eggs.length < 99) { - if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { - this.consumeVouchers(VoucherType.REGULAR, 1); - } - this.pull(); - success = true; - } else { - error = true; - this.showError(i18next.t("egg:tooManyEggs")); - } - break; - case 2: - if (!this.scene.gameData.voucherCounts[VoucherType.PLUS] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { - error = true; - this.showError(i18next.t("egg:notEnoughVouchers")); - } else if (this.scene.gameData.eggs.length < 95) { - if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { - this.consumeVouchers(VoucherType.PLUS, 1); - } - this.pull(5); - success = true; - } else { - error = true; - this.showError(i18next.t("egg:tooManyEggs")); - } - break; - case 1: - case 3: - if ((this.cursor === 1 && this.scene.gameData.voucherCounts[VoucherType.REGULAR] < 10 && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) + case Button.ACTION: + switch (this.cursor) { + case 0: + if (!this.scene.gameData.voucherCounts[VoucherType.REGULAR] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { + error = true; + this.showError(i18next.t("egg:notEnoughVouchers")); + } else if (this.scene.gameData.eggs.length < 99 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) { + if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { + this.consumeVouchers(VoucherType.REGULAR, 1); + } + this.pull(); + success = true; + } else { + error = true; + this.showError(i18next.t("egg:tooManyEggs")); + } + break; + case 2: + if (!this.scene.gameData.voucherCounts[VoucherType.PLUS] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { + error = true; + this.showError(i18next.t("egg:notEnoughVouchers")); + } else if (this.scene.gameData.eggs.length < 95 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) { + if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { + this.consumeVouchers(VoucherType.PLUS, 1); + } + this.pull(5); + success = true; + } else { + error = true; + this.showError(i18next.t("egg:tooManyEggs")); + } + break; + case 1: + case 3: + if ((this.cursor === 1 && this.scene.gameData.voucherCounts[VoucherType.REGULAR] < 10 && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) || (this.cursor === 3 && !this.scene.gameData.voucherCounts[VoucherType.PREMIUM] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE)) { - error = true; - this.showError(i18next.t("egg:notEnoughVouchers")); - } else if (this.scene.gameData.eggs.length < 90) { - if (this.cursor === 3) { - if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { - this.consumeVouchers(VoucherType.PREMIUM, 1); + error = true; + this.showError(i18next.t("egg:notEnoughVouchers")); + } else if (this.scene.gameData.eggs.length < 90 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) { + if (this.cursor === 3) { + if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { + this.consumeVouchers(VoucherType.PREMIUM, 1); + } + } else { + if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { + this.consumeVouchers(VoucherType.REGULAR, 10); + } + } + this.pull(10); + success = true; + } else { + error = true; + this.showError(i18next.t("egg:tooManyEggs")); } - } else { - if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { - this.consumeVouchers(VoucherType.REGULAR, 10); + break; + case 4: + if (!this.scene.gameData.voucherCounts[VoucherType.GOLDEN] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { + error = true; + this.showError(i18next.t("egg:notEnoughVouchers")); + } else if (this.scene.gameData.eggs.length < 75 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) { + if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { + this.consumeVouchers(VoucherType.GOLDEN, 1); + } + this.pull(25); + success = true; + } else { + error = true; + this.showError(i18next.t("egg:tooManyEggs")); } - } - this.pull(10); - success = true; - } else { - error = true; - this.showError(i18next.t("egg:tooManyEggs")); + break; + case 5: + ui.revertMode(); + success = true; + break; } break; - case 4: - if (!this.scene.gameData.voucherCounts[VoucherType.GOLDEN] && !Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { - error = true; - this.showError(i18next.t("egg:notEnoughVouchers")); - } else if (this.scene.gameData.eggs.length < 75) { - if (!Overrides.EGG_FREE_GACHA_PULLS_OVERRIDE) { - this.consumeVouchers(VoucherType.GOLDEN, 1); - } - this.pull(25); - success = true; - } else { - error = true; - this.showError(i18next.t("egg:tooManyEggs")); - } - break; - case 5: - ui.revertMode(); + case Button.CANCEL: + this.getUi().revertMode(); success = true; break; - } - break; - case Button.CANCEL: - this.getUi().revertMode(); - success = true; - break; - case Button.UP: - if (this.cursor) { - success = this.setCursor(this.cursor - 1); - } - break; - case Button.DOWN: - if (this.cursor < 5) { - success = this.setCursor(this.cursor + 1); - } - break; - case Button.LEFT: - if (this.gachaCursor) { - success = this.setGachaCursor(this.gachaCursor - 1); - } - break; - case Button.RIGHT: - if (this.gachaCursor < Utils.getEnumKeys(GachaType).length - 1) { - success = this.setGachaCursor(this.gachaCursor + 1); - } - break; + case Button.UP: + if (this.cursor) { + success = this.setCursor(this.cursor - 1); + } + break; + case Button.DOWN: + if (this.cursor < 5) { + success = this.setCursor(this.cursor + 1); + } + break; + case Button.LEFT: + if (this.gachaCursor) { + success = this.setGachaCursor(this.gachaCursor - 1); + } + break; + case Button.RIGHT: + if (this.gachaCursor < Utils.getEnumKeys(GachaType).length - 1) { + success = this.setGachaCursor(this.gachaCursor + 1); + } + break; } } } diff --git a/src/ui/egg-hatch-scene-handler.ts b/src/ui/egg-hatch-scene-handler.ts index 7b01ef7a3a6..1bf58a786e1 100644 --- a/src/ui/egg-hatch-scene-handler.ts +++ b/src/ui/egg-hatch-scene-handler.ts @@ -1,7 +1,7 @@ import BattleScene from "../battle-scene"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import { EggHatchPhase } from "#app/phases/egg-hatch-phase"; export default class EggHatchSceneHandler extends UiHandler { diff --git a/src/ui/egg-list-ui-handler.ts b/src/ui/egg-list-ui-handler.ts index 0ebc0f8140e..939f95fabe6 100644 --- a/src/ui/egg-list-ui-handler.ts +++ b/src/ui/egg-list-ui-handler.ts @@ -4,7 +4,7 @@ import PokemonIconAnimHandler, { PokemonIconAnimMode } from "#app/ui/pokemon-ico import { TextStyle, addTextObject } from "#app/ui/text"; import MessageUiHandler from "#app/ui/message-ui-handler"; import { addWindow } from "#app/ui/ui-theme"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import i18next from "i18next"; import ScrollableGridUiHandler from "#app/ui/scrollable-grid-handler"; import { ScrollBar } from "#app/ui/scroll-bar"; diff --git a/src/ui/egg-summary-ui-handler.ts b/src/ui/egg-summary-ui-handler.ts index 519722b1505..da93168926e 100644 --- a/src/ui/egg-summary-ui-handler.ts +++ b/src/ui/egg-summary-ui-handler.ts @@ -42,6 +42,9 @@ export default class EggSummaryUiHandler extends MessageUiHandler { private scrollGridHandler : ScrollableGridUiHandler; private cursorObj: Phaser.GameObjects.Image; + /** used to add a delay before which it is not possible to exit the summary */ + private blockExit: boolean; + /** * Allows subscribers to listen for events * @@ -168,6 +171,13 @@ export default class EggSummaryUiHandler extends MessageUiHandler { this.setCursor(0); this.scene.playSoundWithoutBgm("evolution_fanfare"); + + // Prevent exiting the egg summary for 2 seconds if the egg hatching + // was skipped automatically and for 1 second otherwise + const exitBlockingDuration = (this.scene.eggSkipPreference === 2) ? 2000 : 1000; + this.blockExit = true; + this.scene.time.delayedCall(exitBlockingDuration, () => this.blockExit = false); + return true; } @@ -203,13 +213,17 @@ export default class EggSummaryUiHandler extends MessageUiHandler { const ui = this.getUi(); let success = false; - const error = false; + let error = false; if (button === Button.CANCEL) { - const phase = this.scene.getCurrentPhase(); - if (phase instanceof EggSummaryPhase) { - phase.end(); + if (!this.blockExit) { + const phase = this.scene.getCurrentPhase(); + if (phase instanceof EggSummaryPhase) { + phase.end(); + } + success = true; + } else { + error = true; } - success = true; } else { this.scrollGridHandler.processInput(button); } diff --git a/src/ui/evolution-scene-handler.ts b/src/ui/evolution-scene-handler.ts index 76d148d083e..a116a33f373 100644 --- a/src/ui/evolution-scene-handler.ts +++ b/src/ui/evolution-scene-handler.ts @@ -2,7 +2,7 @@ import BattleScene from "../battle-scene"; import MessageUiHandler from "./message-ui-handler"; import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; export default class EvolutionSceneHandler extends MessageUiHandler { public evolutionContainer: Phaser.GameObjects.Container; diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 59d14ab3bc4..ee6641a1a27 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -7,7 +7,7 @@ import UiHandler from "./ui-handler"; import * as Utils from "../utils"; import { MoveCategory } from "#app/data/move"; import i18next from "i18next"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import Pokemon, { PokemonMove } from "#app/field/pokemon"; import { CommandPhase } from "#app/phases/command-phase"; import MoveInfoOverlay from "./move-info-overlay"; @@ -152,26 +152,26 @@ export default class FightUiHandler extends UiHandler implements InfoToggle { } } else { switch (button) { - case Button.UP: - if (cursor >= 2) { - success = this.setCursor(cursor - 2); - } - break; - case Button.DOWN: - if (cursor < 2) { - success = this.setCursor(cursor + 2); - } - break; - case Button.LEFT: - if (cursor % 2 === 1) { - success = this.setCursor(cursor - 1); - } - break; - case Button.RIGHT: - if (cursor % 2 === 0) { - success = this.setCursor(cursor + 1); - } - break; + case Button.UP: + if (cursor >= 2) { + success = this.setCursor(cursor - 2); + } + break; + case Button.DOWN: + if (cursor < 2) { + success = this.setCursor(cursor + 2); + } + break; + case Button.LEFT: + if (cursor % 2 === 1) { + success = this.setCursor(cursor - 1); + } + break; + case Button.RIGHT: + if (cursor % 2 === 0) { + success = this.setCursor(cursor + 1); + } + break; } } @@ -188,7 +188,7 @@ export default class FightUiHandler extends UiHandler implements InfoToggle { this.cursorObj?.setVisible(false); } this.scene.tweens.add({ - targets: [this.movesContainer, this.cursorObj], + targets: [ this.movesContainer, this.cursorObj ], duration: Utils.fixedInt(125), ease: "Sine.easeInOut", alpha: visible ? 0 : 1 diff --git a/src/ui/filter-bar.ts b/src/ui/filter-bar.ts index aa0f575d398..bcf7409fce0 100644 --- a/src/ui/filter-bar.ts +++ b/src/ui/filter-bar.ts @@ -104,11 +104,11 @@ export class FilterBar extends Phaser.GameObjects.Container { totalWidth += label.displayWidth + cursorOffset; }); const spacing = (this.width - totalWidth) / (this.labels.length - 1); - for (let i=0; i { const width = statsBgWidth + 2; const height = Math.floor((this.scene.game.canvas.height / 6) - headerBg.height - 2); - const statsBg = addWindow(this.scene, (statsBgWidth - 2) * i, headerBg.height, width, height, false, false, i>0?-3:0, 1); + const statsBg = addWindow(this.scene, (statsBgWidth - 2) * i, headerBg.height, width, height, false, false, i > 0 ? -3 : 0, 1); statsBg.setOrigin(0, 0); return statsBg; }); @@ -276,9 +276,9 @@ export default class GameStatsUiHandler extends UiHandler { // arrows to show that we can scroll through the stats const isLegacyTheme = this.scene.uiTheme === UiTheme.LEGACY; - this.arrowDown = this.scene.add.sprite(statsBgWidth, this.scene.game.canvas.height / 6 - (isLegacyTheme? 9 : 5), "prompt"); + this.arrowDown = this.scene.add.sprite(statsBgWidth, this.scene.game.canvas.height / 6 - (isLegacyTheme ? 9 : 5), "prompt"); this.gameStatsContainer.add(this.arrowDown); - this.arrowUp = this.scene.add.sprite(statsBgWidth, headerBg.height + (isLegacyTheme? 7 : 3), "prompt"); + this.arrowUp = this.scene.add.sprite(statsBgWidth, headerBg.height + (isLegacyTheme ? 7 : 3), "prompt"); this.arrowUp.flipY = true; this.gameStatsContainer.add(this.arrowUp); @@ -351,16 +351,16 @@ export default class GameStatsUiHandler extends UiHandler { this.scene.ui.revertMode(); } else { switch (button) { - case Button.UP: - if (this.cursor) { - success = this.setCursor(this.cursor - 1); - } - break; - case Button.DOWN: - if (this.cursor < Math.ceil((Object.keys(displayStats).length - 18) / 2)) { - success = this.setCursor(this.cursor + 1); - } - break; + case Button.UP: + if (this.cursor) { + success = this.setCursor(this.cursor - 1); + } + break; + case Button.DOWN: + if (this.cursor < Math.ceil((Object.keys(displayStats).length - 18) / 2)) { + success = this.setCursor(this.cursor + 1); + } + break; } } diff --git a/src/ui/login-form-ui-handler.ts b/src/ui/login-form-ui-handler.ts index 631b2e50b02..8be432ad6c1 100644 --- a/src/ui/login-form-ui-handler.ts +++ b/src/ui/login-form-ui-handler.ts @@ -88,7 +88,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler { } override getButtonLabels(_config?: ModalConfig): string[] { - return [ i18next.t("menu:login"), i18next.t("menu:register")]; + return [ i18next.t("menu:login"), i18next.t("menu:register") ]; } override getReadableErrorMessage(error: string): string { @@ -97,18 +97,18 @@ export default class LoginFormUiHandler extends FormModalUiHandler { error = error.slice(0, colonIndex); } switch (error) { - case this.ERR_USERNAME: - return i18next.t("menu:invalidLoginUsername"); - case this.ERR_PASSWORD: - return i18next.t("menu:invalidLoginPassword"); - case this.ERR_ACCOUNT_EXIST: - return i18next.t("menu:accountNonExistent"); - case this.ERR_PASSWORD_MATCH: - return i18next.t("menu:unmatchingPassword"); - case this.ERR_NO_SAVES: - return i18next.t("menu:noSaves"); - case this.ERR_TOO_MANY_SAVES: - return i18next.t("menu:tooManySaves"); + case this.ERR_USERNAME: + return i18next.t("menu:invalidLoginUsername"); + case this.ERR_PASSWORD: + return i18next.t("menu:invalidLoginPassword"); + case this.ERR_ACCOUNT_EXIST: + return i18next.t("menu:accountNonExistent"); + case this.ERR_PASSWORD_MATCH: + return i18next.t("menu:unmatchingPassword"); + case this.ERR_NO_SAVES: + return i18next.t("menu:noSaves"); + case this.ERR_TOO_MANY_SAVES: + return i18next.t("menu:tooManySaves"); } return super.getReadableErrorMessage(error); @@ -124,7 +124,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler { // Prevent overlapping overrides on action modification this.submitAction = originalLoginAction; this.sanitizeInputs(); - this.scene.ui.setMode(Mode.LOADING, { buttonActions: [] }); + this.scene.ui.setMode(Mode.LOADING, { buttonActions: []}); const onFail = error => { this.scene.ui.setMode(Mode.LOGIN_FORM, Object.assign(config, { errorMessage: error?.trim() })); this.scene.ui.playError(); @@ -161,19 +161,19 @@ export default class LoginFormUiHandler extends FormModalUiHandler { this.infoContainer.setVisible(false); this.setMouseCursorStyle("default"); //reset cursor - [this.discordImage, this.googleImage, this.usernameInfoImage].forEach((img) => img.off("pointerdown")); + [ this.discordImage, this.googleImage, this.usernameInfoImage ].forEach((img) => img.off("pointerdown")); } private processExternalProvider(config: ModalConfig) : void { this.externalPartyTitle.setText(i18next.t("menu:orUse") ?? ""); - this.externalPartyTitle.setX(20+this.externalPartyTitle.text.length); + this.externalPartyTitle.setX(20 + this.externalPartyTitle.text.length); this.externalPartyTitle.setVisible(true); this.externalPartyContainer.setPositionRelative(this.modalContainer, 175, 0); this.externalPartyContainer.setVisible(true); this.externalPartyBg.setSize(this.externalPartyTitle.text.length + 50, this.modalBg.height); this.getUi().moveTo(this.externalPartyContainer, this.getUi().length - 1); - this.googleImage.setPosition(this.externalPartyBg.width/3.1, this.externalPartyBg.height-60); - this.discordImage.setPosition(this.externalPartyBg.width/3.1, this.externalPartyBg.height-40); + this.googleImage.setPosition(this.externalPartyBg.width / 3.1, this.externalPartyBg.height - 60); + this.discordImage.setPosition(this.externalPartyBg.width / 3.1, this.externalPartyBg.height - 40); this.infoContainer.setPosition(5, -76); this.infoContainer.setVisible(true); @@ -195,7 +195,7 @@ export default class LoginFormUiHandler extends FormModalUiHandler { }); const onFail = error => { - this.scene.ui.setMode(Mode.LOADING, { buttonActions: [] }); + this.scene.ui.setMode(Mode.LOADING, { buttonActions: []}); this.scene.ui.setModeForceTransition(Mode.LOGIN_FORM, Object.assign(config, { errorMessage: error?.trim() })); this.scene.ui.playError(); }; diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index 0af527e518f..0f4c2d2f53e 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -65,8 +65,8 @@ export default class MenuUiHandler extends MessageUiHandler { super(scene, mode); this.excludedMenus = () => [ - { condition: [Mode.COMMAND, Mode.TITLE].includes(mode ?? Mode.TITLE), options: [MenuOptions.EGG_GACHA, MenuOptions.EGG_LIST] }, - { condition: bypassLogin, options: [MenuOptions.LOG_OUT] } + { condition: [ Mode.COMMAND, Mode.TITLE ].includes(mode ?? Mode.TITLE), options: [ MenuOptions.EGG_GACHA, MenuOptions.EGG_LIST ]}, + { condition: bypassLogin, options: [ MenuOptions.LOG_OUT ]} ]; this.menuOptions = Utils.getEnumKeys(MenuOptions) @@ -80,7 +80,7 @@ export default class MenuUiHandler extends MessageUiHandler { const ui = this.getUi(); // wiki url directs based on languges available on wiki const lang = i18next.resolvedLanguage?.substring(0, 2)!; // TODO: is this bang correct? - if (["de", "fr", "ko", "zh"].includes(lang)) { + if ([ "de", "fr", "ko", "zh" ].includes(lang)) { wikiUrl = `https://wiki.pokerogue.net/${lang}:start`; } @@ -108,8 +108,8 @@ export default class MenuUiHandler extends MessageUiHandler { render() { const ui = this.getUi(); this.excludedMenus = () => [ - { condition: this.scene.getCurrentPhase() instanceof SelectModifierPhase, options: [MenuOptions.EGG_GACHA, MenuOptions.EGG_LIST] }, - { condition: bypassLogin, options: [MenuOptions.LOG_OUT] } + { condition: this.scene.getCurrentPhase() instanceof SelectModifierPhase, options: [ MenuOptions.EGG_GACHA, MenuOptions.EGG_LIST ]}, + { condition: bypassLogin, options: [ MenuOptions.LOG_OUT ]} ]; this.menuOptions = Utils.getEnumKeys(MenuOptions) @@ -468,148 +468,148 @@ export default class MenuUiHandler extends MessageUiHandler { } this.showText("", 0); switch (adjustedCursor) { - case MenuOptions.GAME_SETTINGS: - ui.setOverlayMode(Mode.SETTINGS); - success = true; - break; - case MenuOptions.ACHIEVEMENTS: - ui.setOverlayMode(Mode.ACHIEVEMENTS); - success = true; - break; - case MenuOptions.STATS: - ui.setOverlayMode(Mode.GAME_STATS); - success = true; - break; - case MenuOptions.RUN_HISTORY: - ui.setOverlayMode(Mode.RUN_HISTORY); - success = true; - break; - case MenuOptions.EGG_LIST: - if (this.scene.gameData.eggs.length) { + case MenuOptions.GAME_SETTINGS: + ui.setOverlayMode(Mode.SETTINGS); + success = true; + break; + case MenuOptions.ACHIEVEMENTS: + ui.setOverlayMode(Mode.ACHIEVEMENTS); + success = true; + break; + case MenuOptions.STATS: + ui.setOverlayMode(Mode.GAME_STATS); + success = true; + break; + case MenuOptions.RUN_HISTORY: + ui.setOverlayMode(Mode.RUN_HISTORY); + success = true; + break; + case MenuOptions.EGG_LIST: + if (this.scene.gameData.eggs.length) { + ui.revertMode(); + ui.setOverlayMode(Mode.EGG_LIST); + success = true; + } else { + ui.showText(i18next.t("menuUiHandler:noEggs"), null, () => ui.showText(""), Utils.fixedInt(1500)); + error = true; + } + break; + case MenuOptions.EGG_GACHA: ui.revertMode(); - ui.setOverlayMode(Mode.EGG_LIST); + ui.setOverlayMode(Mode.EGG_GACHA); success = true; - } else { - ui.showText(i18next.t("menuUiHandler:noEggs"), null, () => ui.showText(""), Utils.fixedInt(1500)); - error = true; - } - break; - case MenuOptions.EGG_GACHA: - ui.revertMode(); - ui.setOverlayMode(Mode.EGG_GACHA); - success = true; - break; - case MenuOptions.MANAGE_DATA: - if (!bypassLogin && !this.manageDataConfig.options.some(o => o.label === i18next.t("menuUiHandler:linkDiscord") || o.label === i18next.t("menuUiHandler:unlinkDiscord"))) { - this.manageDataConfig.options.splice(this.manageDataConfig.options.length - 1, 0, - { - label: loggedInUser?.discordId === "" ? i18next.t("menuUiHandler:linkDiscord") : i18next.t("menuUiHandler:unlinkDiscord"), - handler: () => { - if (loggedInUser?.discordId === "") { - const token = Utils.getCookie(Utils.sessionIdKey); - const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); - const discordId = import.meta.env.VITE_DISCORD_CLIENT_ID; - const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify&state=${token}&prompt=none`; - window.open(discordUrl, "_self"); - return true; - } else { - Utils.apiPost("/auth/discord/logout", undefined, undefined, true).then(res => { - if (!res.ok) { - console.error(`Unlink failed (${res.status}: ${res.statusText})`); - } - updateUserInfo().then(() => this.scene.reset(true, true)); - }); - return true; + break; + case MenuOptions.MANAGE_DATA: + if (!bypassLogin && !this.manageDataConfig.options.some(o => o.label === i18next.t("menuUiHandler:linkDiscord") || o.label === i18next.t("menuUiHandler:unlinkDiscord"))) { + this.manageDataConfig.options.splice(this.manageDataConfig.options.length - 1, 0, + { + label: loggedInUser?.discordId === "" ? i18next.t("menuUiHandler:linkDiscord") : i18next.t("menuUiHandler:unlinkDiscord"), + handler: () => { + if (loggedInUser?.discordId === "") { + const token = Utils.getCookie(Utils.sessionIdKey); + const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/discord/callback`); + const discordId = import.meta.env.VITE_DISCORD_CLIENT_ID; + const discordUrl = `https://discord.com/api/oauth2/authorize?client_id=${discordId}&redirect_uri=${redirectUri}&response_type=code&scope=identify&state=${token}&prompt=none`; + window.open(discordUrl, "_self"); + return true; + } else { + Utils.apiPost("/auth/discord/logout", undefined, undefined, true).then(res => { + if (!res.ok) { + console.error(`Unlink failed (${res.status}: ${res.statusText})`); + } + updateUserInfo().then(() => this.scene.reset(true, true)); + }); + return true; + } } - } - }, - { - label: loggedInUser?.googleId === "" ? i18next.t("menuUiHandler:linkGoogle") : i18next.t("menuUiHandler:unlinkGoogle"), - handler: () => { - if (loggedInUser?.googleId === "") { - const token = Utils.getCookie(Utils.sessionIdKey); - const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/google/callback`); - const googleId = import.meta.env.VITE_GOOGLE_CLIENT_ID; - const googleUrl = `https://accounts.google.com/o/oauth2/auth?client_id=${googleId}&response_type=code&redirect_uri=${redirectUri}&scope=openid&state=${token}`; - window.open(googleUrl, "_self"); - return true; - } else { - Utils.apiPost("/auth/google/logout", undefined, undefined, true).then(res => { - if (!res.ok) { - console.error(`Unlink failed (${res.status}: ${res.statusText})`); - } - updateUserInfo().then(() => this.scene.reset(true, true)); - }); - return true; + }, + { + label: loggedInUser?.googleId === "" ? i18next.t("menuUiHandler:linkGoogle") : i18next.t("menuUiHandler:unlinkGoogle"), + handler: () => { + if (loggedInUser?.googleId === "") { + const token = Utils.getCookie(Utils.sessionIdKey); + const redirectUri = encodeURIComponent(`${import.meta.env.VITE_SERVER_URL}/auth/google/callback`); + const googleId = import.meta.env.VITE_GOOGLE_CLIENT_ID; + const googleUrl = `https://accounts.google.com/o/oauth2/auth?client_id=${googleId}&response_type=code&redirect_uri=${redirectUri}&scope=openid&state=${token}`; + window.open(googleUrl, "_self"); + return true; + } else { + Utils.apiPost("/auth/google/logout", undefined, undefined, true).then(res => { + if (!res.ok) { + console.error(`Unlink failed (${res.status}: ${res.statusText})`); + } + updateUserInfo().then(() => this.scene.reset(true, true)); + }); + return true; + } } - } - }); - } - ui.setOverlayMode(Mode.MENU_OPTION_SELECT, this.manageDataConfig); - success = true; - break; - case MenuOptions.COMMUNITY: - ui.setOverlayMode(Mode.MENU_OPTION_SELECT, this.communityConfig); - success = true; - break; - case MenuOptions.SAVE_AND_QUIT: - if (this.scene.currentBattle) { + }); + } + ui.setOverlayMode(Mode.MENU_OPTION_SELECT, this.manageDataConfig); success = true; - const doSaveQuit = () => { - ui.setMode(Mode.LOADING, { - buttonActions: [], fadeOut: () => - this.scene.gameData.saveAll(this.scene, true, true, true, true).then(() => { + break; + case MenuOptions.COMMUNITY: + ui.setOverlayMode(Mode.MENU_OPTION_SELECT, this.communityConfig); + success = true; + break; + case MenuOptions.SAVE_AND_QUIT: + if (this.scene.currentBattle) { + success = true; + const doSaveQuit = () => { + ui.setMode(Mode.LOADING, { + buttonActions: [], fadeOut: () => + this.scene.gameData.saveAll(this.scene, true, true, true, true).then(() => { - this.scene.reset(true); - }) + this.scene.reset(true); + }) + }); + }; + if (this.scene.currentBattle.turn > 1) { + ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => { + if (!this.active) { + this.showText("", 0); + return; + } + ui.setOverlayMode(Mode.CONFIRM, doSaveQuit, () => { + ui.revertMode(); + this.showText("", 0); + }, false, -98); + }); + } else { + doSaveQuit(); + } + } else { + error = true; + } + break; + case MenuOptions.LOG_OUT: + success = true; + const doLogout = () => { + ui.setMode(Mode.LOADING, { + buttonActions: [], fadeOut: () => Utils.apiFetch("account/logout", true).then(res => { + if (!res.ok) { + console.error(`Log out failed (${res.status}: ${res.statusText})`); + } + Utils.removeCookie(Utils.sessionIdKey); + updateUserInfo().then(() => this.scene.reset(true, true)); + }) }); }; - if (this.scene.currentBattle.turn > 1) { + if (this.scene.currentBattle) { ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => { if (!this.active) { this.showText("", 0); return; } - ui.setOverlayMode(Mode.CONFIRM, doSaveQuit, () => { + ui.setOverlayMode(Mode.CONFIRM, doLogout, () => { ui.revertMode(); this.showText("", 0); }, false, -98); }); } else { - doSaveQuit(); + doLogout(); } - } else { - error = true; - } - break; - case MenuOptions.LOG_OUT: - success = true; - const doLogout = () => { - ui.setMode(Mode.LOADING, { - buttonActions: [], fadeOut: () => Utils.apiFetch("account/logout", true).then(res => { - if (!res.ok) { - console.error(`Log out failed (${res.status}: ${res.statusText})`); - } - Utils.removeCookie(Utils.sessionIdKey); - updateUserInfo().then(() => this.scene.reset(true, true)); - }) - }); - }; - if (this.scene.currentBattle) { - ui.showText(i18next.t("menuUiHandler:losingProgressionWarning"), null, () => { - if (!this.active) { - this.showText("", 0); - return; - } - ui.setOverlayMode(Mode.CONFIRM, doLogout, () => { - ui.revertMode(); - this.showText("", 0); - }, false, -98); - }); - } else { - doLogout(); - } - break; + break; } } else if (button === Button.CANCEL) { success = true; @@ -620,20 +620,20 @@ export default class MenuUiHandler extends MessageUiHandler { }); } else { switch (button) { - case Button.UP: - if (this.cursor) { - success = this.setCursor(this.cursor - 1); - } else { - success = this.setCursor(this.menuOptions.length - 1); - } - break; - case Button.DOWN: - if (this.cursor + 1 < this.menuOptions.length) { - success = this.setCursor(this.cursor + 1); - } else { - success = this.setCursor(0); - } - break; + case Button.UP: + if (this.cursor) { + success = this.setCursor(this.cursor - 1); + } else { + success = this.setCursor(this.menuOptions.length - 1); + } + break; + case Button.DOWN: + if (this.cursor + 1 < this.menuOptions.length) { + success = this.setCursor(this.cursor + 1); + } else { + success = this.setCursor(0); + } + break; } } diff --git a/src/ui/message-ui-handler.ts b/src/ui/message-ui-handler.ts index f1b8ed981ee..5ae4707e329 100644 --- a/src/ui/message-ui-handler.ts +++ b/src/ui/message-ui-handler.ts @@ -56,18 +56,18 @@ export default abstract class MessageUiHandler extends AwaitableUiHandler { let actionMatch: RegExpExecArray | null; while ((actionMatch = actionPattern.exec(text))) { switch (actionMatch[1]) { - case "c": - charVarMap.set(actionMatch.index, actionMatch[2]); - break; - case "d": - delayMap.set(actionMatch.index, parseInt(actionMatch[2])); - break; - case "s": - soundMap.set(actionMatch.index, actionMatch[2]); - break; - case "f": - fadeMap.set(actionMatch.index, parseInt(actionMatch[2])); - break; + case "c": + charVarMap.set(actionMatch.index, actionMatch[2]); + break; + case "d": + delayMap.set(actionMatch.index, parseInt(actionMatch[2])); + break; + case "s": + soundMap.set(actionMatch.index, actionMatch[2]); + break; + case "f": + fadeMap.set(actionMatch.index, parseInt(actionMatch[2])); + break; } text = text.slice(0, actionMatch.index) + text.slice(actionMatch.index + actionMatch[2].length + 4); } diff --git a/src/ui/modal-ui-handler.ts b/src/ui/modal-ui-handler.ts index 80a39d7bf7f..60204f18c4a 100644 --- a/src/ui/modal-ui-handler.ts +++ b/src/ui/modal-ui-handler.ts @@ -3,7 +3,7 @@ import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import { WindowVariant, addWindow } from "./ui-theme"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; export interface ModalConfig { buttonActions: Function[]; @@ -92,7 +92,7 @@ export abstract class ModalUiHandler extends UiHandler { if (args[0].hasOwnProperty("fadeOut") && typeof args[0].fadeOut === "function") { const [ marginTop, marginRight, marginBottom, marginLeft ] = this.getMargin(); - const overlay = this.scene.add.rectangle(( this.getWidth() + marginLeft + marginRight) / 2, (this.getHeight() + marginTop + marginBottom) / 2, this.scene.game.canvas.width / 6, this.scene.game.canvas.height /6, 0); + const overlay = this.scene.add.rectangle(( this.getWidth() + marginLeft + marginRight) / 2, (this.getHeight() + marginTop + marginBottom) / 2, this.scene.game.canvas.width / 6, this.scene.game.canvas.height / 6, 0); overlay.setOrigin(0.5, 0.5); overlay.setName("rect-ui-overlay-modal"); overlay.setAlpha(0); diff --git a/src/ui/modifier-select-ui-handler.ts b/src/ui/modifier-select-ui-handler.ts index a1e10d74c64..3f89ebe415f 100644 --- a/src/ui/modifier-select-ui-handler.ts +++ b/src/ui/modifier-select-ui-handler.ts @@ -16,7 +16,10 @@ import { ShopCursorTarget } from "#app/enums/shop-cursor-target"; import { IntegerHolder } from "./../utils"; import Phaser from "phaser"; -export const SHOP_OPTIONS_ROW_LIMIT = 6; +export const SHOP_OPTIONS_ROW_LIMIT = 7; +const SINGLE_SHOP_ROW_YOFFSET = 12; +const DOUBLE_SHOP_ROW_YOFFSET = 24; +const OPTION_BUTTON_YPOSITION = -62; export default class ModifierSelectUiHandler extends AwaitableUiHandler { private modifierContainer: Phaser.GameObjects.Container; @@ -68,7 +71,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { this.checkButtonWidth = context.measureText(i18next.t("modifierSelectUiHandler:checkTeam")).width; } - this.transferButtonContainer = this.scene.add.container((this.scene.game.canvas.width - this.checkButtonWidth) / 6 - 21, -64); + this.transferButtonContainer = this.scene.add.container((this.scene.game.canvas.width - this.checkButtonWidth) / 6 - 21, OPTION_BUTTON_YPOSITION); this.transferButtonContainer.setName("transfer-btn"); this.transferButtonContainer.setVisible(false); ui.add(this.transferButtonContainer); @@ -78,7 +81,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { transferButtonText.setOrigin(1, 0); this.transferButtonContainer.add(transferButtonText); - this.checkButtonContainer = this.scene.add.container((this.scene.game.canvas.width) / 6 - 1, -64); + this.checkButtonContainer = this.scene.add.container((this.scene.game.canvas.width) / 6 - 1, OPTION_BUTTON_YPOSITION); this.checkButtonContainer.setName("use-btn"); this.checkButtonContainer.setVisible(false); ui.add(this.checkButtonContainer); @@ -88,7 +91,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { checkButtonText.setOrigin(1, 0); this.checkButtonContainer.add(checkButtonText); - this.rerollButtonContainer = this.scene.add.container(16, -64); + this.rerollButtonContainer = this.scene.add.container(16, OPTION_BUTTON_YPOSITION); this.rerollButtonContainer.setName("reroll-brn"); this.rerollButtonContainer.setVisible(false); ui.add(this.rerollButtonContainer); @@ -104,7 +107,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { this.rerollCostText.setPositionRelative(rerollButtonText, rerollButtonText.displayWidth + 5, 1); this.rerollButtonContainer.add(this.rerollCostText); - this.lockRarityButtonContainer = this.scene.add.container(16, -64); + this.lockRarityButtonContainer = this.scene.add.container(16, OPTION_BUTTON_YPOSITION); this.lockRarityButtonContainer.setVisible(false); ui.add(this.lockRarityButtonContainer); @@ -191,7 +194,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { const shopTypeOptions = !removeHealShop ? getPlayerShopModifierTypeOptionsForWave(this.scene.currentBattle.waveIndex, baseShopCost.value) : []; - const optionsYOffset = shopTypeOptions.length >= SHOP_OPTIONS_ROW_LIMIT ? -8 : -24; + const optionsYOffset = shopTypeOptions.length > SHOP_OPTIONS_ROW_LIMIT ? -SINGLE_SHOP_ROW_YOFFSET : -DOUBLE_SHOP_ROW_YOFFSET; for (let m = 0; m < typeOptions.length; m++) { const sliceWidth = (this.scene.game.canvas.width / 6) / (typeOptions.length + 2); @@ -211,8 +214,8 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { const row = m < SHOP_OPTIONS_ROW_LIMIT ? 0 : 1; const col = m < SHOP_OPTIONS_ROW_LIMIT ? m : m - SHOP_OPTIONS_ROW_LIMIT; const rowOptions = shopTypeOptions.slice(row ? SHOP_OPTIONS_ROW_LIMIT : 0, row ? undefined : SHOP_OPTIONS_ROW_LIMIT); - const sliceWidth = (this.scene.game.canvas.width / SHOP_OPTIONS_ROW_LIMIT) / (rowOptions.length + 2); - const option = new ModifierOption(this.scene, sliceWidth * (col + 1) + (sliceWidth * 0.5), ((-this.scene.game.canvas.height / 12) - (this.scene.game.canvas.height / 32) - (40 - (28 * row - 1))), shopTypeOptions[m]); + const sliceWidth = (this.scene.game.canvas.width / 6) / (rowOptions.length + 2); + const option = new ModifierOption(this.scene, sliceWidth * (col + 1) + (sliceWidth * 0.5), ((-this.scene.game.canvas.height / 12) - (this.scene.game.canvas.height / 32) - (42 - (28 * row - 1))), shopTypeOptions[m]); option.setScale(0.375); this.scene.add.existing(option); this.modifierContainer.add(option); @@ -283,7 +286,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { }); this.scene.tweens.add({ - targets: [this.rerollButtonContainer, this.lockRarityButtonContainer], + targets: [ this.rerollButtonContainer, this.lockRarityButtonContainer ], alpha: this.rerollCost < 0 ? 0.5 : 1, duration: 250 }); @@ -354,79 +357,79 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { } } else { switch (button) { - case Button.UP: - if (this.rowCursor === 0 && this.cursor === 3) { - success = this.setCursor(0); - } else if (this.rowCursor < this.shopOptionsRows.length + 1) { - success = this.setRowCursor(this.rowCursor + 1); - } - break; - case Button.DOWN: - if (this.rowCursor) { - success = this.setRowCursor(this.rowCursor - 1); - } else if (this.lockRarityButtonContainer.visible && this.cursor === 0) { - success = this.setCursor(3); - } - break; - case Button.LEFT: - if (!this.rowCursor) { - switch (this.cursor) { - case 0: - success = false; - break; - case 1: - if (this.lockRarityButtonContainer.visible) { - success = this.setCursor(3); - } else { - success = this.rerollButtonContainer.visible && this.setCursor(0); - } - break; - case 2: - if (this.transferButtonContainer.visible) { - success = this.setCursor(1); - } else if (this.rerollButtonContainer.visible) { - success = this.setCursor(0); - } else { - success = false; - } - break; + case Button.UP: + if (this.rowCursor === 0 && this.cursor === 3) { + success = this.setCursor(0); + } else if (this.rowCursor < this.shopOptionsRows.length + 1) { + success = this.setRowCursor(this.rowCursor + 1); } - } else if (this.cursor) { - success = this.setCursor(this.cursor - 1); - } else if (this.rowCursor === 1 && this.rerollButtonContainer.visible) { - success = this.setRowCursor(0); - } - break; - case Button.RIGHT: - if (!this.rowCursor) { - switch (this.cursor) { - case 0: - if (this.transferButtonContainer.visible) { - success = this.setCursor(1); - } else { - success = this.setCursor(2); - } - break; - case 1: - success = this.setCursor(2); - break; - case 2: - success = false; - break; - case 3: - if (this.transferButtonContainer.visible) { - success = this.setCursor(1); - } else { - success = this.setCursor(2); - } - break; + break; + case Button.DOWN: + if (this.rowCursor) { + success = this.setRowCursor(this.rowCursor - 1); + } else if (this.lockRarityButtonContainer.visible && this.cursor === 0) { + success = this.setCursor(3); } - } else if (this.cursor < this.getRowItems(this.rowCursor) - 1) { - success = this.setCursor(this.cursor + 1); - } else if (this.rowCursor === 1 && this.transferButtonContainer.visible) { - success = this.setRowCursor(0); - } - break; + break; + case Button.LEFT: + if (!this.rowCursor) { + switch (this.cursor) { + case 0: + success = false; + break; + case 1: + if (this.lockRarityButtonContainer.visible) { + success = this.setCursor(3); + } else { + success = this.rerollButtonContainer.visible && this.setCursor(0); + } + break; + case 2: + if (this.transferButtonContainer.visible) { + success = this.setCursor(1); + } else if (this.rerollButtonContainer.visible) { + success = this.setCursor(0); + } else { + success = false; + } + break; + } + } else if (this.cursor) { + success = this.setCursor(this.cursor - 1); + } else if (this.rowCursor === 1 && this.rerollButtonContainer.visible) { + success = this.setRowCursor(0); + } + break; + case Button.RIGHT: + if (!this.rowCursor) { + switch (this.cursor) { + case 0: + if (this.transferButtonContainer.visible) { + success = this.setCursor(1); + } else { + success = this.setCursor(2); + } + break; + case 1: + success = this.setCursor(2); + break; + case 2: + success = false; + break; + case 3: + if (this.transferButtonContainer.visible) { + success = this.setCursor(1); + } else { + success = this.setCursor(2); + } + break; + } + } else if (this.cursor < this.getRowItems(this.rowCursor) - 1) { + success = this.setCursor(this.cursor + 1); + } else if (this.rowCursor === 1 && this.transferButtonContainer.visible) { + success = this.setRowCursor(0); + } + break; } } @@ -456,16 +459,18 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { if (this.rowCursor === 1 && options.length === 0) { // Continue button when no shop items this.cursorObj.setScale(1.25); - this.cursorObj.setPosition((this.scene.game.canvas.width / 18) + 23, (-this.scene.game.canvas.height / 12) - (this.shopOptionsRows.length > 1 ? 6 : 22)); + this.cursorObj.setPosition((this.scene.game.canvas.width / 18) + 23, (-this.scene.game.canvas.height / 12) - (this.shopOptionsRows.length > 1 ? SINGLE_SHOP_ROW_YOFFSET - 2 : DOUBLE_SHOP_ROW_YOFFSET - 2)); ui.showText(i18next.t("modifierSelectUiHandler:continueNextWaveDescription")); return ret; } const sliceWidth = (this.scene.game.canvas.width / 6) / (options.length + 2); if (this.rowCursor < 2) { - this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 20, (-this.scene.game.canvas.height / 12) - (this.shopOptionsRows.length > 1 ? 6 : 22)); + // Cursor on free items + this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 20, (-this.scene.game.canvas.height / 12) - (this.shopOptionsRows.length > 1 ? SINGLE_SHOP_ROW_YOFFSET - 2 : DOUBLE_SHOP_ROW_YOFFSET - 2)); } else { - this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 16, (-this.scene.game.canvas.height / 12 - this.scene.game.canvas.height / 32) - (-16 + 28 * (this.rowCursor - (this.shopOptionsRows.length - 1)))); + // Cursor on paying items + this.cursorObj.setPosition(sliceWidth * (cursor + 1) + (sliceWidth * 0.5) - 16, (-this.scene.game.canvas.height / 12 - this.scene.game.canvas.height / 32) - (-14 + 28 * (this.rowCursor - (this.shopOptionsRows.length - 1)))); } const type = options[this.cursor].modifierTypeOption.type; @@ -475,16 +480,16 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { this.moveInfoOverlay.show(allMoves[type.moveId]); } } else if (cursor === 0) { - this.cursorObj.setPosition(6, this.lockRarityButtonContainer.visible ? -72 : -60); + this.cursorObj.setPosition(6, this.lockRarityButtonContainer.visible ? OPTION_BUTTON_YPOSITION - 8 : OPTION_BUTTON_YPOSITION + 4); ui.showText(i18next.t("modifierSelectUiHandler:rerollDesc")); } else if (cursor === 1) { - this.cursorObj.setPosition((this.scene.game.canvas.width - this.transferButtonWidth - this.checkButtonWidth) / 6 - 30, -60); + this.cursorObj.setPosition((this.scene.game.canvas.width - this.transferButtonWidth - this.checkButtonWidth) / 6 - 30, OPTION_BUTTON_YPOSITION + 4); ui.showText(i18next.t("modifierSelectUiHandler:transferDesc")); } else if (cursor === 2) { - this.cursorObj.setPosition((this.scene.game.canvas.width - this.checkButtonWidth) / 6 - 10, -60); + this.cursorObj.setPosition((this.scene.game.canvas.width - this.checkButtonWidth) / 6 - 10, OPTION_BUTTON_YPOSITION + 4); ui.showText(i18next.t("modifierSelectUiHandler:checkTeamDesc")); } else { - this.cursorObj.setPosition(6, -60); + this.cursorObj.setPosition(6, OPTION_BUTTON_YPOSITION + 4); ui.showText(i18next.t("modifierSelectUiHandler:lockRaritiesDesc")); } @@ -522,12 +527,12 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { private getRowItems(rowCursor: integer): integer { switch (rowCursor) { - case 0: - return 3; - case 1: - return this.options.length; - default: - return this.shopOptionsRows[this.shopOptionsRows.length - (rowCursor - 1)].length; + case 0: + return 3; + case 1: + return this.options.length; + default: + return this.shopOptionsRows[this.shopOptionsRows.length - (rowCursor - 1)].length; } } @@ -577,6 +582,10 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { this.getUi().clearText(); this.eraseCursor(); + // Reset cursor positions + this.cursor = 0; + this.rowCursor = 0; + /* Multiplies the fade time duration by the speed parameter so that it is always constant, and avoids "flashbangs" at game speed x5 */ this.scene.hideShopOverlay(750 * this.scene.gameSpeed); this.scene.hideLuckText(250); diff --git a/src/ui/move-info-overlay.ts b/src/ui/move-info-overlay.ts index 42026082b36..6c58d32c515 100644 --- a/src/ui/move-info-overlay.ts +++ b/src/ui/move-info-overlay.ts @@ -1,4 +1,4 @@ -import BattleScene, {InfoToggle} from "../battle-scene"; +import BattleScene, { InfoToggle } from "../battle-scene"; import { TextStyle, addTextObject } from "./text"; import { addWindow } from "./ui-theme"; import * as Utils from "../utils"; @@ -62,7 +62,7 @@ export default class MoveInfoOverlay extends Phaser.GameObjects.Container implem this.add(this.descBg); // set up the description; wordWrap uses true pixels, unaffected by any scaling, while other values are affected - this.desc = addTextObject(scene, (options?.onSide && !options?.right ? EFF_WIDTH : 0) + BORDER, (options?.top ? EFF_HEIGHT : 0) + BORDER - 2, "", TextStyle.BATTLE_INFO, { wordWrap: { width: (width - (BORDER - 2) * 2 - (options?.onSide ? EFF_WIDTH : 0)) * GLOBAL_SCALE } }); + this.desc = addTextObject(scene, (options?.onSide && !options?.right ? EFF_WIDTH : 0) + BORDER, (options?.top ? EFF_HEIGHT : 0) + BORDER - 2, "", TextStyle.BATTLE_INFO, { wordWrap: { width: (width - (BORDER - 2) * 2 - (options?.onSide ? EFF_WIDTH : 0)) * GLOBAL_SCALE }}); this.desc.setLineSpacing(i18next.resolvedLanguage === "ja" ? 25 : 5); // limit the text rendering, required for scrolling later on diff --git a/src/ui/mystery-encounter-ui-handler.ts b/src/ui/mystery-encounter-ui-handler.ts index edff5c25cda..b568f8b71de 100644 --- a/src/ui/mystery-encounter-ui-handler.ts +++ b/src/ui/mystery-encounter-ui-handler.ts @@ -159,16 +159,16 @@ export default class MysteryEncounterUiHandler extends UiHandler { } } else { switch (this.optionsContainer.getAll()?.length) { - default: - case 3: - success = this.handleTwoOptionMoveInput(button); - break; - case 4: - success = this.handleThreeOptionMoveInput(button); - break; - case 5: - success = this.handleFourOptionMoveInput(button); - break; + default: + case 3: + success = this.handleTwoOptionMoveInput(button); + break; + case 4: + success = this.handleThreeOptionMoveInput(button); + break; + case 5: + success = this.handleFourOptionMoveInput(button); + break; } this.displayOptionTooltip(); @@ -185,26 +185,26 @@ export default class MysteryEncounterUiHandler extends UiHandler { let success = false; const cursor = this.getCursor(); switch (button) { - case Button.UP: - if (cursor < this.viewPartyIndex) { - success = this.setCursor(this.viewPartyIndex); - } - break; - case Button.DOWN: - if (cursor === this.viewPartyIndex) { - success = this.setCursor(1); - } - break; - case Button.LEFT: - if (cursor > 0) { - success = this.setCursor(cursor - 1); - } - break; - case Button.RIGHT: - if (cursor < this.viewPartyIndex) { - success = this.setCursor(cursor + 1); - } - break; + case Button.UP: + if (cursor < this.viewPartyIndex) { + success = this.setCursor(this.viewPartyIndex); + } + break; + case Button.DOWN: + if (cursor === this.viewPartyIndex) { + success = this.setCursor(1); + } + break; + case Button.LEFT: + if (cursor > 0) { + success = this.setCursor(cursor - 1); + } + break; + case Button.RIGHT: + if (cursor < this.viewPartyIndex) { + success = this.setCursor(cursor + 1); + } + break; } return success; @@ -214,34 +214,34 @@ export default class MysteryEncounterUiHandler extends UiHandler { let success = false; const cursor = this.getCursor(); switch (button) { - case Button.UP: - if (cursor === 2) { - success = this.setCursor(cursor - 2); - } else { - success = this.setCursor(this.viewPartyIndex); - } - break; - case Button.DOWN: - if (cursor === this.viewPartyIndex) { - success = this.setCursor(1); - } else { - success = this.setCursor(2); - } - break; - case Button.LEFT: - if (cursor === this.viewPartyIndex) { - success = this.setCursor(1); - } else if (cursor === 1) { - success = this.setCursor(cursor - 1); - } - break; - case Button.RIGHT: - if (cursor === 1) { - success = this.setCursor(this.viewPartyIndex); - } else if (cursor < 1) { - success = this.setCursor(cursor + 1); - } - break; + case Button.UP: + if (cursor === 2) { + success = this.setCursor(cursor - 2); + } else { + success = this.setCursor(this.viewPartyIndex); + } + break; + case Button.DOWN: + if (cursor === this.viewPartyIndex) { + success = this.setCursor(1); + } else { + success = this.setCursor(2); + } + break; + case Button.LEFT: + if (cursor === this.viewPartyIndex) { + success = this.setCursor(1); + } else if (cursor === 1) { + success = this.setCursor(cursor - 1); + } + break; + case Button.RIGHT: + if (cursor === 1) { + success = this.setCursor(this.viewPartyIndex); + } else if (cursor < 1) { + success = this.setCursor(cursor + 1); + } + break; } return success; @@ -251,34 +251,34 @@ export default class MysteryEncounterUiHandler extends UiHandler { let success = false; const cursor = this.getCursor(); switch (button) { - case Button.UP: - if (cursor >= 2 && cursor !== this.viewPartyIndex) { - success = this.setCursor(cursor - 2); - } else { - success = this.setCursor(this.viewPartyIndex); - } - break; - case Button.DOWN: - if (cursor <= 1) { - success = this.setCursor(cursor + 2); - } else if (cursor === this.viewPartyIndex) { - success = this.setCursor(1); - } - break; - case Button.LEFT: - if (cursor === this.viewPartyIndex) { - success = this.setCursor(1); - } else if (cursor % 2 === 1) { - success = this.setCursor(cursor - 1); - } - break; - case Button.RIGHT: - if (cursor === 1) { - success = this.setCursor(this.viewPartyIndex); - } else if (cursor % 2 === 0 && cursor !== this.viewPartyIndex) { - success = this.setCursor(cursor + 1); - } - break; + case Button.UP: + if (cursor >= 2 && cursor !== this.viewPartyIndex) { + success = this.setCursor(cursor - 2); + } else { + success = this.setCursor(this.viewPartyIndex); + } + break; + case Button.DOWN: + if (cursor <= 1) { + success = this.setCursor(cursor + 2); + } else if (cursor === this.viewPartyIndex) { + success = this.setCursor(1); + } + break; + case Button.LEFT: + if (cursor === this.viewPartyIndex) { + success = this.setCursor(1); + } else if (cursor % 2 === 1) { + success = this.setCursor(cursor - 1); + } + break; + case Button.RIGHT: + if (cursor === 1) { + success = this.setCursor(this.viewPartyIndex); + } else if (cursor % 2 === 0 && cursor !== this.viewPartyIndex) { + success = this.setCursor(cursor + 1); + } + break; } return success; @@ -351,16 +351,16 @@ export default class MysteryEncounterUiHandler extends UiHandler { let optionText: BBCodeText; switch (this.encounterOptions.length) { - default: - case 2: - optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, 8, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 }); - break; - case 3: - optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 }); - break; - case 4: - optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 }); - break; + default: + case 2: + optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, 8, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 }); + break; + case 3: + optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 }); + break; + case 4: + optionText = addBBCodeTextObject(this.scene, i % 2 === 0 ? 0 : 100, i < 2 ? 0 : 16, "-", TextStyle.WINDOW, { fontSize: "80px", lineSpacing: -8 }); + break; } this.optionsMeetsReqs.push(option.meetsRequirements(this.scene)); @@ -438,7 +438,7 @@ export default class MysteryEncounterUiHandler extends UiHandler { const ballType = getPokeballAtlasKey(index); this.rarityBall.setTexture("pb", ballType); - const descriptionTextObject = addBBCodeTextObject(this.scene, 6, 25, descriptionText ?? "", TextStyle.TOOLTIP_CONTENT, { wordWrap: { width: 830 } }); + const descriptionTextObject = addBBCodeTextObject(this.scene, 6, 25, descriptionText ?? "", TextStyle.TOOLTIP_CONTENT, { wordWrap: { width: 830 }}); // Sets up the mask that hides the description text to give an illusion of scrolling const descriptionTextMaskRect = this.scene.make.graphics({}); @@ -472,7 +472,7 @@ export default class MysteryEncounterUiHandler extends UiHandler { this.descriptionContainer.add(descriptionTextObject); - const queryTextObject = addBBCodeTextObject(this.scene, 0, 0, queryText ?? "", TextStyle.TOOLTIP_CONTENT, { wordWrap: { width: 830 } }); + const queryTextObject = addBBCodeTextObject(this.scene, 0, 0, queryText ?? "", TextStyle.TOOLTIP_CONTENT, { wordWrap: { width: 830 }}); this.descriptionContainer.add(queryTextObject); queryTextObject.setPosition(75 - queryTextObject.displayWidth / 2, 90); @@ -518,7 +518,7 @@ export default class MysteryEncounterUiHandler extends UiHandler { // Auto-color options green/blue for good/bad by looking for (+)/(-) if (text) { - const primaryStyleString = [...text.match(new RegExp(/\[color=[^\[]*\]\[shadow=[^\[]*\]/i))!][0]; + const primaryStyleString = [ ...text.match(new RegExp(/\[color=[^\[]*\]\[shadow=[^\[]*\]/i))! ][0]; text = text.replace(/(\(\+\)[^\(\[]*)/gi, substring => "[/color][/shadow]" + getBBCodeFrag(substring, TextStyle.SUMMARY_GREEN) + "[/color][/shadow]" + primaryStyleString); text = text.replace(/(\(\-\)[^\(\[]*)/gi, substring => "[/color][/shadow]" + getBBCodeFrag(substring, TextStyle.SUMMARY_BLUE) + "[/color][/shadow]" + primaryStyleString); } diff --git a/src/ui/outdated-modal-ui-handler.ts b/src/ui/outdated-modal-ui-handler.ts deleted file mode 100644 index fc4b93f9b8a..00000000000 --- a/src/ui/outdated-modal-ui-handler.ts +++ /dev/null @@ -1,47 +0,0 @@ -import BattleScene from "../battle-scene"; -import { ModalConfig, ModalUiHandler } from "./modal-ui-handler"; -import { addTextObject, TextStyle } from "./text"; -import { Mode } from "./ui"; - -export default class OutdatedModalUiHandler extends ModalUiHandler { - constructor(scene: BattleScene, mode: Mode | null = null) { - super(scene, mode); - } - - getModalTitle(): string { - return ""; - } - - getWidth(): number { - return 160; - } - - getHeight(): number { - return 64; - } - - getMargin(): [number, number, number, number] { - return [ 0, 0, 48, 0 ]; - } - - getButtonLabels(): string[] { - return [ ]; - } - - setup(): void { - super.setup(); - - const label = addTextObject(this.scene, this.getWidth() / 2, this.getHeight() / 2, "Your client is currently outdated.\nPlease reload to update the game.\n\nIf this error persists, please clear your browser cache.", TextStyle.WINDOW, { fontSize: "48px", align: "center" }); - label.setOrigin(0.5, 0.5); - - this.modalContainer.add(label); - } - - show(args: any[]): boolean { - const config: ModalConfig = { - buttonActions: [] - }; - - return super.show([ config ]); - } -} diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 72b34731842..e96fde8d54f 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -14,7 +14,7 @@ import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { addWindow } from "#app/ui/ui-theme"; import { SpeciesFormChangeItemTrigger, FormChangeItem } from "#app/data/pokemon-forms"; import { getVariantTint } from "#app/data/variant"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import { applyChallenges, ChallengeType } from "#app/data/challenge"; import MoveInfoOverlay from "#app/ui/move-info-overlay"; import i18next from "i18next"; @@ -216,7 +216,7 @@ export default class PartyUiHandler extends MessageUiHandler { public static NoEffectMessage = i18next.t("partyUiHandler:anyEffect"); - private localizedOptions = [PartyOption.SEND_OUT, PartyOption.SUMMARY, PartyOption.CANCEL, PartyOption.APPLY, PartyOption.RELEASE, PartyOption.TEACH, PartyOption.SPLICE, PartyOption.UNSPLICE, PartyOption.REVIVE, PartyOption.TRANSFER, PartyOption.UNPAUSE_EVOLUTION, PartyOption.PASS_BATON, PartyOption.RENAME, PartyOption.SELECT]; + private localizedOptions = [ PartyOption.SEND_OUT, PartyOption.SUMMARY, PartyOption.CANCEL, PartyOption.APPLY, PartyOption.RELEASE, PartyOption.TEACH, PartyOption.SPLICE, PartyOption.UNSPLICE, PartyOption.REVIVE, PartyOption.TRANSFER, PartyOption.UNPAUSE_EVOLUTION, PartyOption.PASS_BATON, PartyOption.RENAME, PartyOption.SELECT ]; constructor(scene: BattleScene) { super(scene, Mode.PARTY); @@ -468,7 +468,7 @@ export default class PartyUiHandler extends MessageUiHandler { this.clearOptions(); ui.playSelect(); pokemon.pauseEvolutions = !pokemon.pauseEvolutions; - this.showText(i18next.t(pokemon.pauseEvolutions? "partyUiHandler:pausedEvolutions" : "partyUiHandler:unpausedEvolutions", { pokemonName: getPokemonNameWithAffix(pokemon) }), undefined, () => this.showText("", 0), null, true); + this.showText(i18next.t(pokemon.pauseEvolutions ? "partyUiHandler:pausedEvolutions" : "partyUiHandler:unpausedEvolutions", { pokemonName: getPokemonNameWithAffix(pokemon) }), undefined, () => this.showText("", 0), null, true); } else if (option === PartyOption.UNSPLICE) { this.clearOptions(); ui.playSelect(); @@ -539,42 +539,42 @@ export default class PartyUiHandler extends MessageUiHandler { return true; } else { switch (button) { - case Button.LEFT: + case Button.LEFT: /** Decrease quantity for the current item and update UI */ - if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { - this.transferQuantities[option] = this.transferQuantities[option] === 1 ? this.transferQuantitiesMax[option] : this.transferQuantities[option] - 1; - this.updateOptions(); - success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */ - } - break; - case Button.RIGHT: + if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { + this.transferQuantities[option] = this.transferQuantities[option] === 1 ? this.transferQuantitiesMax[option] : this.transferQuantities[option] - 1; + this.updateOptions(); + success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */ + } + break; + case Button.RIGHT: /** Increase quantity for the current item and update UI */ - if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { - this.transferQuantities[option] = this.transferQuantities[option] === this.transferQuantitiesMax[option] ? 1 : this.transferQuantities[option] + 1; - this.updateOptions(); - success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */ - } - break; - case Button.UP: - /** If currently selecting items to transfer, reset quantity selection */ - if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { - if (option !== PartyOption.ALL) { - this.transferQuantities[option] = this.transferQuantitiesMax[option]; + if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { + this.transferQuantities[option] = this.transferQuantities[option] === this.transferQuantitiesMax[option] ? 1 : this.transferQuantities[option] + 1; + this.updateOptions(); + success = this.setCursor(this.optionsCursor); /** Place again the cursor at the same position. Necessary, otherwise the cursor disappears */ } - this.updateOptions(); - } - success = this.setCursor(this.optionsCursor ? this.optionsCursor - 1 : this.options.length - 1); /** Move cursor */ - break; - case Button.DOWN: + break; + case Button.UP: /** If currently selecting items to transfer, reset quantity selection */ - if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { - if (option !== PartyOption.ALL) { - this.transferQuantities[option] = this.transferQuantitiesMax[option]; + if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { + if (option !== PartyOption.ALL) { + this.transferQuantities[option] = this.transferQuantitiesMax[option]; + } + this.updateOptions(); } - this.updateOptions(); - } - success = this.setCursor(this.optionsCursor < this.options.length - 1 ? this.optionsCursor + 1 : 0); /** Move cursor */ - break; + success = this.setCursor(this.optionsCursor ? this.optionsCursor - 1 : this.options.length - 1); /** Move cursor */ + break; + case Button.DOWN: + /** If currently selecting items to transfer, reset quantity selection */ + if (this.partyUiMode === PartyUiMode.MODIFIER_TRANSFER) { + if (option !== PartyOption.ALL) { + this.transferQuantities[option] = this.transferQuantitiesMax[option]; + } + this.updateOptions(); + } + success = this.setCursor(this.optionsCursor < this.options.length - 1 ? this.optionsCursor + 1 : 0); /** Move cursor */ + break; } // show move description @@ -631,28 +631,28 @@ export default class PartyUiHandler extends MessageUiHandler { const battlerCount = this.scene.currentBattle.getBattlerCount(); switch (button) { - case Button.UP: - success = this.setCursor(this.cursor ? this.cursor < 6 ? this.cursor - 1 : slotCount - 1 : 6); - break; - case Button.DOWN: - success = this.setCursor(this.cursor < 6 ? this.cursor < slotCount - 1 ? this.cursor + 1 : 6 : 0); - break; - case Button.LEFT: - if (this.cursor >= battlerCount && this.cursor <= 6) { - success = this.setCursor(0); - } - break; - case Button.RIGHT: - if (slotCount === battlerCount) { - success = this.setCursor(6); + case Button.UP: + success = this.setCursor(this.cursor ? this.cursor < 6 ? this.cursor - 1 : slotCount - 1 : 6); break; - } else if (battlerCount >= 2 && slotCount > battlerCount && this.getCursor() === 0 && this.lastCursor === 1) { - success = this.setCursor(2); + case Button.DOWN: + success = this.setCursor(this.cursor < 6 ? this.cursor < slotCount - 1 ? this.cursor + 1 : 6 : 0); break; - } else if (slotCount > battlerCount && this.cursor < battlerCount) { - success = this.setCursor(this.lastCursor < 6 ? this.lastCursor || battlerCount : battlerCount); + case Button.LEFT: + if (this.cursor >= battlerCount && this.cursor <= 6) { + success = this.setCursor(0); + } break; - } + case Button.RIGHT: + if (slotCount === battlerCount) { + success = this.setCursor(6); + break; + } else if (battlerCount >= 2 && slotCount > battlerCount && this.getCursor() === 0 && this.lastCursor === 1) { + success = this.setCursor(2); + break; + } else if (slotCount > battlerCount && this.cursor < battlerCount) { + success = this.setCursor(this.lastCursor < 6 ? this.lastCursor || battlerCount : battlerCount); + break; + } } } @@ -671,6 +671,9 @@ export default class PartyUiHandler extends MessageUiHandler { } else if (this.cursor === 6) { this.partyCancelButton.select(); } + if (this.lastCursor < 6 && this.lastCursor >= party.length) { + this.lastCursor = party.length - 1; + } for (const p in party) { const slotIndex = parseInt(p); @@ -770,19 +773,19 @@ export default class PartyUiHandler extends MessageUiHandler { let optionsMessage = i18next.t("partyUiHandler:doWhatWithThisPokemon"); switch (this.partyUiMode) { - case PartyUiMode.MOVE_MODIFIER: - optionsMessage = i18next.t("partyUiHandler:selectAMove"); - break; - case PartyUiMode.MODIFIER_TRANSFER: - if (!this.transferMode) { - optionsMessage = i18next.t("partyUiHandler:changeQuantity"); - } - break; - case PartyUiMode.SPLICE: - if (!this.transferMode) { - optionsMessage = i18next.t("partyUiHandler:selectAnotherPokemonToSplice"); - } - break; + case PartyUiMode.MOVE_MODIFIER: + optionsMessage = i18next.t("partyUiHandler:selectAMove"); + break; + case PartyUiMode.MODIFIER_TRANSFER: + if (!this.transferMode) { + optionsMessage = i18next.t("partyUiHandler:changeQuantity"); + } + break; + case PartyUiMode.SPLICE: + if (!this.transferMode) { + optionsMessage = i18next.t("partyUiHandler:selectAnotherPokemonToSplice"); + } + break; } this.showText(optionsMessage, 0); @@ -826,64 +829,64 @@ export default class PartyUiHandler extends MessageUiHandler { if (this.partyUiMode !== PartyUiMode.MOVE_MODIFIER && this.partyUiMode !== PartyUiMode.REMEMBER_MOVE_MODIFIER && (this.transferMode || this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER)) { switch (this.partyUiMode) { - case PartyUiMode.SWITCH: - case PartyUiMode.FAINT_SWITCH: - case PartyUiMode.POST_BATTLE_SWITCH: - if (this.cursor >= this.scene.currentBattle.getBattlerCount()) { - const allowBatonModifierSwitch = + case PartyUiMode.SWITCH: + case PartyUiMode.FAINT_SWITCH: + case PartyUiMode.POST_BATTLE_SWITCH: + if (this.cursor >= this.scene.currentBattle.getBattlerCount()) { + const allowBatonModifierSwitch = this.partyUiMode !== PartyUiMode.FAINT_SWITCH && this.scene.findModifier(m => m instanceof SwitchEffectTransferModifier && (m as SwitchEffectTransferModifier).pokemonId === this.scene.getPlayerField()[this.fieldIndex].id); - const moveHistory = this.scene.getPlayerField()[this.fieldIndex].getMoveHistory(); - const isBatonPassMove = this.partyUiMode === PartyUiMode.FAINT_SWITCH && moveHistory.length && allMoves[moveHistory[moveHistory.length - 1].move].getAttrs(ForceSwitchOutAttr)[0]?.isBatonPass() && moveHistory[moveHistory.length - 1].result === MoveResult.SUCCESS; + const moveHistory = this.scene.getPlayerField()[this.fieldIndex].getMoveHistory(); + const isBatonPassMove = this.partyUiMode === PartyUiMode.FAINT_SWITCH && moveHistory.length && allMoves[moveHistory[moveHistory.length - 1].move].getAttrs(ForceSwitchOutAttr)[0]?.isBatonPass() && moveHistory[moveHistory.length - 1].result === MoveResult.SUCCESS; - // isBatonPassMove and allowBatonModifierSwitch shouldn't ever be true - // at the same time, because they both explicitly check for a mutually - // exclusive partyUiMode. But better safe than sorry. - this.options.push(isBatonPassMove && !allowBatonModifierSwitch ? PartyOption.PASS_BATON : PartyOption.SEND_OUT); - if (allowBatonModifierSwitch && !isBatonPassMove) { + // isBatonPassMove and allowBatonModifierSwitch shouldn't ever be true + // at the same time, because they both explicitly check for a mutually + // exclusive partyUiMode. But better safe than sorry. + this.options.push(isBatonPassMove && !allowBatonModifierSwitch ? PartyOption.PASS_BATON : PartyOption.SEND_OUT); + if (allowBatonModifierSwitch && !isBatonPassMove) { // the BATON modifier gives an extra switch option for // pokemon-command switches, allowing buffs to be optionally passed - this.options.push(PartyOption.PASS_BATON); + this.options.push(PartyOption.PASS_BATON); + } } - } - break; - case PartyUiMode.REVIVAL_BLESSING: - this.options.push(PartyOption.REVIVE); - break; - case PartyUiMode.MODIFIER: - this.options.push(PartyOption.APPLY); - break; - case PartyUiMode.TM_MODIFIER: - this.options.push(PartyOption.TEACH); - break; - case PartyUiMode.MODIFIER_TRANSFER: - this.options.push(PartyOption.TRANSFER); - break; - case PartyUiMode.SPLICE: - if (this.transferMode) { - if (this.cursor !== this.transferCursor) { - this.options.push(PartyOption.SPLICE); - } - } else { + break; + case PartyUiMode.REVIVAL_BLESSING: + this.options.push(PartyOption.REVIVE); + break; + case PartyUiMode.MODIFIER: this.options.push(PartyOption.APPLY); - } - break; - case PartyUiMode.RELEASE: - this.options.push(PartyOption.RELEASE); - break; - case PartyUiMode.CHECK: - if (this.scene.getCurrentPhase() instanceof SelectModifierPhase) { - formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon); - for (let i = 0; i < formChangeItemModifiers.length; i++) { - this.options.push(PartyOption.FORM_CHANGE_ITEM + i); + break; + case PartyUiMode.TM_MODIFIER: + this.options.push(PartyOption.TEACH); + break; + case PartyUiMode.MODIFIER_TRANSFER: + this.options.push(PartyOption.TRANSFER); + break; + case PartyUiMode.SPLICE: + if (this.transferMode) { + if (this.cursor !== this.transferCursor) { + this.options.push(PartyOption.SPLICE); + } + } else { + this.options.push(PartyOption.APPLY); } - } - break; - case PartyUiMode.SELECT: - this.options.push(PartyOption.SELECT); - break; + break; + case PartyUiMode.RELEASE: + this.options.push(PartyOption.RELEASE); + break; + case PartyUiMode.CHECK: + if (this.scene.getCurrentPhase() instanceof SelectModifierPhase) { + formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon); + for (let i = 0; i < formChangeItemModifiers.length; i++) { + this.options.push(PartyOption.FORM_CHANGE_ITEM + i); + } + } + break; + case PartyUiMode.SELECT: + this.options.push(PartyOption.SELECT); + break; } this.options.push(PartyOption.SUMMARY); @@ -959,33 +962,33 @@ export default class PartyUiHandler extends MessageUiHandler { optionName = "↓"; } else if ((this.partyUiMode !== PartyUiMode.REMEMBER_MOVE_MODIFIER && (this.partyUiMode !== PartyUiMode.MODIFIER_TRANSFER || this.transferMode)) || option === PartyOption.CANCEL) { switch (option) { - case PartyOption.MOVE_1: - case PartyOption.MOVE_2: - case PartyOption.MOVE_3: - case PartyOption.MOVE_4: - const move = pokemon.moveset[option - PartyOption.MOVE_1]!; // TODO: is the bang correct? - if (this.showMovePp) { - const maxPP = move.getMovePp(); - const currPP = maxPP - move.ppUsed; - optionName = `${move.getName()} ${currPP}/${maxPP}`; - } else { - optionName = move.getName(); - } - break; - default: - if (formChangeItemModifiers && option >= PartyOption.FORM_CHANGE_ITEM) { - const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM]; - optionName = `${modifier.active ? i18next.t("partyUiHandler:DEACTIVATE") : i18next.t("partyUiHandler:ACTIVATE")} ${modifier.type.name}`; - } else if (option === PartyOption.UNPAUSE_EVOLUTION) { - optionName = `${pokemon.pauseEvolutions ? i18next.t("partyUiHandler:UNPAUSE_EVOLUTION") : i18next.t("partyUiHandler:PAUSE_EVOLUTION")}`; - } else { - if (this.localizedOptions.includes(option)) { - optionName = i18next.t(`partyUiHandler:${PartyOption[option]}`); + case PartyOption.MOVE_1: + case PartyOption.MOVE_2: + case PartyOption.MOVE_3: + case PartyOption.MOVE_4: + const move = pokemon.moveset[option - PartyOption.MOVE_1]!; // TODO: is the bang correct? + if (this.showMovePp) { + const maxPP = move.getMovePp(); + const currPP = maxPP - move.ppUsed; + optionName = `${move.getName()} ${currPP}/${maxPP}`; } else { - optionName = Utils.toReadableString(PartyOption[option]); + optionName = move.getName(); } - } - break; + break; + default: + if (formChangeItemModifiers && option >= PartyOption.FORM_CHANGE_ITEM) { + const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM]; + optionName = `${modifier.active ? i18next.t("partyUiHandler:DEACTIVATE") : i18next.t("partyUiHandler:ACTIVATE")} ${modifier.type.name}`; + } else if (option === PartyOption.UNPAUSE_EVOLUTION) { + optionName = `${pokemon.pauseEvolutions ? i18next.t("partyUiHandler:UNPAUSE_EVOLUTION") : i18next.t("partyUiHandler:PAUSE_EVOLUTION")}`; + } else { + if (this.localizedOptions.includes(option)) { + optionName = i18next.t(`partyUiHandler:${PartyOption[option]}`); + } else { + optionName = Utils.toReadableString(PartyOption[option]); + } + } + break; } } else if (this.partyUiMode === PartyUiMode.REMEMBER_MOVE_MODIFIER) { const move = learnableLevelMoves[option]; @@ -1240,7 +1243,7 @@ class PartySlot extends Phaser.GameObjects.Container { slotLevelText.setPositionRelative(slotLevelLabel, 9, 0); slotLevelText.setOrigin(0, 0.25); - slotInfoContainer.add([this.slotName, slotLevelLabel, slotLevelText ]); + slotInfoContainer.add([ this.slotName, slotLevelLabel, slotLevelText ]); const genderSymbol = getGenderSymbol(this.pokemon.getGender(true)); @@ -1323,7 +1326,7 @@ class PartySlot extends Phaser.GameObjects.Container { this.slotDescriptionLabel.setOrigin(0, 1); this.slotDescriptionLabel.setVisible(false); - slotInfoContainer.add([this.slotHpBar, this.slotHpOverlay, this.slotHpText, this.slotDescriptionLabel]); + slotInfoContainer.add([ this.slotHpBar, this.slotHpOverlay, this.slotHpText, this.slotDescriptionLabel ]); if (partyUiMode !== PartyUiMode.TM_MODIFIER) { this.slotDescriptionLabel.setVisible(false); diff --git a/src/ui/pokemon-hatch-info-container.ts b/src/ui/pokemon-hatch-info-container.ts index 2c3f5110f53..146d70522fd 100644 --- a/src/ui/pokemon-hatch-info-container.ts +++ b/src/ui/pokemon-hatch-info-container.ts @@ -47,11 +47,11 @@ export default class PokemonHatchInfoContainer extends PokemonInfoContainer { this.pokemonListContainer.add(this.currentPokemonSprite); // setup name and number - this.pokemonNumberText = addTextObject(this.scene, 80, 107.5, "0000", TextStyle.SUMMARY, {fontSize: 74}); + this.pokemonNumberText = addTextObject(this.scene, 80, 107.5, "0000", TextStyle.SUMMARY, { fontSize: 74 }); this.pokemonNumberText.setOrigin(0, 0); this.pokemonListContainer.add(this.pokemonNumberText); - this.pokemonNameText = addTextObject(this.scene, 7, 107.5, "", TextStyle.SUMMARY, {fontSize: 74}); + this.pokemonNameText = addTextObject(this.scene, 7, 107.5, "", TextStyle.SUMMARY, { fontSize: 74 }); this.pokemonNameText.setOrigin(0, 0); this.pokemonListContainer.add(this.pokemonNameText); @@ -89,7 +89,7 @@ export default class PokemonHatchInfoContainer extends PokemonInfoContainer { const eggMoveBg = this.scene.add.nineslice(70, 0, "type_bgs", "unknown", 92, 14, 2, 2, 2, 2); eggMoveBg.setOrigin(1, 0); - const eggMoveLabel = addTextObject(this.scene, 70 -eggMoveBg.width / 2, 0, "???", TextStyle.PARTY); + const eggMoveLabel = addTextObject(this.scene, 70 - eggMoveBg.width / 2, 0, "???", TextStyle.PARTY); eggMoveLabel.setOrigin(0.5, 0); this.pokemonEggMoveBgs.push(eggMoveBg); diff --git a/src/ui/pokemon-icon-anim-handler.ts b/src/ui/pokemon-icon-anim-handler.ts index d6796d5cb5d..c7a24f69200 100644 --- a/src/ui/pokemon-icon-anim-handler.ts +++ b/src/ui/pokemon-icon-anim-handler.ts @@ -39,12 +39,12 @@ export default class PokemonIconAnimHandler { getModeYDelta(mode: PokemonIconAnimMode): number { switch (mode) { - case PokemonIconAnimMode.NONE: - return 0; - case PokemonIconAnimMode.PASSIVE: - return -1; - case PokemonIconAnimMode.ACTIVE: - return -2; + case PokemonIconAnimMode.NONE: + return 0; + case PokemonIconAnimMode.PASSIVE: + return -1; + case PokemonIconAnimMode.ACTIVE: + return -2; } } diff --git a/src/ui/registration-form-ui-handler.ts b/src/ui/registration-form-ui-handler.ts index 0c4b54ac723..2f8486bcdb3 100644 --- a/src/ui/registration-form-ui-handler.ts +++ b/src/ui/registration-form-ui-handler.ts @@ -50,12 +50,12 @@ export default class RegistrationFormUiHandler extends FormModalUiHandler { error = error.slice(0, colonIndex); } switch (error) { - case "invalid username": - return i18next.t("menu:invalidRegisterUsername"); - case "invalid password": - return i18next.t("menu:invalidRegisterPassword"); - case "failed to add account record": - return i18next.t("menu:usernameAlreadyUsed"); + case "invalid username": + return i18next.t("menu:invalidRegisterUsername"); + case "invalid password": + return i18next.t("menu:invalidRegisterPassword"); + case "failed to add account record": + return i18next.t("menu:usernameAlreadyUsed"); } return super.getReadableErrorMessage(error); @@ -74,7 +74,7 @@ export default class RegistrationFormUiHandler extends FormModalUiHandler { }); const warningMessageFontSize = languageSettings[i18next.resolvedLanguage!]?.warningMessageFontSize ?? "42px"; - const label = addTextObject(this.scene, 10, 87, i18next.t("menu:registrationAgeWarning"), TextStyle.TOOLTIP_CONTENT, { fontSize: warningMessageFontSize}); + const label = addTextObject(this.scene, 10, 87, i18next.t("menu:registrationAgeWarning"), TextStyle.TOOLTIP_CONTENT, { fontSize: warningMessageFontSize }); this.modalContainer.add(label); } @@ -88,7 +88,7 @@ export default class RegistrationFormUiHandler extends FormModalUiHandler { // Prevent overlapping overrides on action modification this.submitAction = originalRegistrationAction; this.sanitizeInputs(); - this.scene.ui.setMode(Mode.LOADING, { buttonActions: [] }); + this.scene.ui.setMode(Mode.LOADING, { buttonActions: []}); const onFail = error => { this.scene.ui.setMode(Mode.REGISTRATION_FORM, Object.assign(config, { errorMessage: error?.trim() })); this.scene.ui.playError(); diff --git a/src/ui/run-history-ui-handler.ts b/src/ui/run-history-ui-handler.ts index d983fb0b0b8..061f15d0956 100644 --- a/src/ui/run-history-ui-handler.ts +++ b/src/ui/run-history-ui-handler.ts @@ -7,11 +7,12 @@ import * as Utils from "../utils"; import PokemonData from "../system/pokemon-data"; import MessageUiHandler from "./message-ui-handler"; import i18next from "i18next"; -import {Button} from "../enums/buttons"; +import { Button } from "../enums/buttons"; import { BattleType } from "../battle"; import { RunEntry } from "../system/game-data"; import { PlayerGender } from "#enums/player-gender"; import { TrainerVariant } from "../field/trainer"; +import { RunDisplayMode } from "#app/ui/run-info-ui-handler"; export type RunSelectCallback = (cursor: number) => void; @@ -100,11 +101,11 @@ export default class RunHistoryUiHandler extends MessageUiHandler { let success = false; const error = false; - if ([Button.ACTION, Button.CANCEL].includes(button)) { + if ([ Button.ACTION, Button.CANCEL ].includes(button)) { if (button === Button.ACTION) { const cursor = this.cursor + this.scrollCursor; if (this.runs[cursor]) { - this.scene.ui.setOverlayMode(Mode.RUN_INFO, this.runs[cursor].entryData, true); + this.scene.ui.setOverlayMode(Mode.RUN_INFO, this.runs[cursor].entryData, RunDisplayMode.RUN_HISTORY, true); } else { return false; } @@ -117,28 +118,28 @@ export default class RunHistoryUiHandler extends MessageUiHandler { } } else if (this.runs.length > 0) { switch (button) { - case Button.UP: - if (this.cursor) { - success = this.setCursor(this.cursor - 1); - } else if (this.scrollCursor) { - success = this.setScrollCursor(this.scrollCursor - 1); - } else if (this.runs.length > 1) { + case Button.UP: + if (this.cursor) { + success = this.setCursor(this.cursor - 1); + } else if (this.scrollCursor) { + success = this.setScrollCursor(this.scrollCursor - 1); + } else if (this.runs.length > 1) { // wrap around to the bottom - success = this.setCursor(Math.min(this.runs.length - 1, this.maxRows - 1)); - success = this.setScrollCursor(Math.max(0, this.runs.length - this.maxRows)) || success; - } - break; - case Button.DOWN: - if (this.cursor < Math.min(this.maxRows - 1, this.runs.length - this.scrollCursor - 1)) { - success = this.setCursor(this.cursor + 1); - } else if (this.scrollCursor < this.runs.length - this.maxRows) { - success = this.setScrollCursor(this.scrollCursor + 1); - } else if (this.runs.length > 1) { + success = this.setCursor(Math.min(this.runs.length - 1, this.maxRows - 1)); + success = this.setScrollCursor(Math.max(0, this.runs.length - this.maxRows)) || success; + } + break; + case Button.DOWN: + if (this.cursor < Math.min(this.maxRows - 1, this.runs.length - this.scrollCursor - 1)) { + success = this.setCursor(this.cursor + 1); + } else if (this.scrollCursor < this.runs.length - this.maxRows) { + success = this.setScrollCursor(this.scrollCursor + 1); + } else if (this.runs.length > 1) { // wrap around to the top - success = this.setCursor(0); - success = this.setScrollCursor(0) || success; - } - break; + success = this.setCursor(0); + success = this.setScrollCursor(0) || success; + } + break; } } @@ -186,8 +187,8 @@ export default class RunHistoryUiHandler extends MessageUiHandler { const emptyWindow = addWindow(this.scene, 0, 0, 304, 165); this.runsContainer.add(emptyWindow); const emptyWindowCoordinates = emptyWindow.getCenter(); - const emptyText = addTextObject(this.scene, 0, 0, i18next.t("saveSlotSelectUiHandler:empty"), TextStyle.WINDOW, {fontSize: "128px"}); - emptyText.setPosition(emptyWindowCoordinates.x-18, emptyWindowCoordinates.y-15); + const emptyText = addTextObject(this.scene, 0, 0, i18next.t("saveSlotSelectUiHandler:empty"), TextStyle.WINDOW, { fontSize: "128px" }); + emptyText.setPosition(emptyWindowCoordinates.x - 18, emptyWindowCoordinates.y - 15); this.runsContainer.add(emptyText); } @@ -255,7 +256,7 @@ class RunEntryContainer extends Phaser.GameObjects.Container { public entryData: RunEntry; constructor(scene: BattleScene, entryData: RunEntry, slotId: number) { - super(scene, 0, slotId*56); + super(scene, 0, slotId * 56); this.slotId = slotId; this.entryData = entryData; @@ -295,7 +296,7 @@ class RunEntryContainer extends Phaser.GameObjects.Container { const gameOutcomeLabel = addTextObject(this.scene, 0, 0, `${i18next.t("runHistory:defeatedWild", { context: genderStr })}`, TextStyle.WINDOW); enemyContainer.add(gameOutcomeLabel); data.enemyParty.forEach((enemyData, e) => { - const enemyIconContainer = this.scene.add.container(65+(e*25), -8); + const enemyIconContainer = this.scene.add.container(65 + (e * 25), -8); enemyIconContainer.setScale(0.75); enemyData.boss = false; enemyData["player"] = true; @@ -332,33 +333,33 @@ class RunEntryContainer extends Phaser.GameObjects.Container { const gameModeLabel = addTextObject(this.scene, 8, 19, "", TextStyle.WINDOW); let mode = ""; switch (data.gameMode) { - case GameModes.DAILY: - mode = i18next.t("gameMode:dailyRun"); - break; - case GameModes.SPLICED_ENDLESS: - case GameModes.ENDLESS: - mode = i18next.t("gameMode:endless"); - break; - case GameModes.CLASSIC: - mode = i18next.t("gameMode:classic"); - break; - case GameModes.CHALLENGE: - mode = i18next.t("gameMode:challenge"); - break; + case GameModes.DAILY: + mode = i18next.t("gameMode:dailyRun"); + break; + case GameModes.SPLICED_ENDLESS: + case GameModes.ENDLESS: + mode = i18next.t("gameMode:endless"); + break; + case GameModes.CLASSIC: + mode = i18next.t("gameMode:classic"); + break; + case GameModes.CHALLENGE: + mode = i18next.t("gameMode:challenge"); + break; } gameModeLabel.appendText(mode, false); if (data.gameMode === GameModes.SPLICED_ENDLESS) { const splicedIcon = this.scene.add.image(0, 0, "icon_spliced"); splicedIcon.setScale(0.75); const coords = gameModeLabel.getTopRight(); - splicedIcon.setPosition(coords.x+5, 27); + splicedIcon.setPosition(coords.x + 5, 27); this.add(splicedIcon); // 4 spaces of room for the Spliced icon gameModeLabel.appendText(" - ", false); } else { gameModeLabel.appendText(" - ", false); } - gameModeLabel.appendText(i18next.t("saveSlotSelectUiHandler:wave")+" "+data.waveIndex, false); + gameModeLabel.appendText(i18next.t("saveSlotSelectUiHandler:wave") + " " + data.waveIndex, false); this.add(gameModeLabel); const timestampLabel = addTextObject(this.scene, 8, 33, new Date(data.timestamp).toLocaleString(), TextStyle.WINDOW); diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index b4e4ad1130d..0ca47241136 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -5,10 +5,11 @@ import { SessionSaveData } from "../system/game-data"; import { TextStyle, addTextObject, addBBCodeTextObject, getTextColor } from "./text"; import { Mode } from "./ui"; import { addWindow } from "./ui-theme"; +import { getPokeballAtlasKey } from "#app/data/pokeball"; import * as Utils from "../utils"; import PokemonData from "../system/pokemon-data"; import i18next from "i18next"; -import {Button} from "../enums/buttons"; +import { Button } from "../enums/buttons"; import { BattleType } from "../battle"; import { TrainerVariant } from "../field/trainer"; import { Challenges } from "#enums/challenges"; @@ -22,6 +23,8 @@ import * as Modifier from "../modifier/modifier"; import { Species } from "#enums/species"; import { PlayerGender } from "#enums/player-gender"; import { SettingKeyboard } from "#app/system/settings/settings-keyboard"; +import { getBiomeName } from "#app/data/balance/biomes"; +import { MysteryEncounterType } from "#enums/mystery-encounter-type"; /** * RunInfoUiMode indicates possible overlays of RunInfoUiHandler. @@ -34,6 +37,11 @@ enum RunInfoUiMode { ENDING_ART } +export enum RunDisplayMode { + RUN_HISTORY, + SESSION_PREVIEW +} + /** * Some variables are protected because this UI class will most likely be extended in the future to display more information. * These variables will most likely be shared across 'classes' aka pages. @@ -41,6 +49,7 @@ enum RunInfoUiMode { * For now, I leave as is. */ export default class RunInfoUiHandler extends UiHandler { + protected runDisplayMode: RunDisplayMode; protected runInfo: SessionSaveData; protected isVictory: boolean; protected pageMode: RunInfoUiMode; @@ -66,6 +75,7 @@ export default class RunInfoUiHandler extends UiHandler { // The import of the modifiersModule is loaded here to sidestep async/await issues. this.modifiersModule = Modifier; this.runContainer.setVisible(false); + this.scene.loadImage("encounter_exclaim", "mystery-encounters"); } /** @@ -87,9 +97,15 @@ export default class RunInfoUiHandler extends UiHandler { this.runContainer.add(gameStatsBg); const run = args[0]; + this.runDisplayMode = args[1]; + if (this.runDisplayMode === RunDisplayMode.RUN_HISTORY) { + this.runInfo = this.scene.gameData.parseSessionData(JSON.stringify(run.entry)); + this.isVictory = run.isVictory ?? false; + } else if (this.runDisplayMode === RunDisplayMode.SESSION_PREVIEW) { + this.runInfo = args[0]; + } // Assigning information necessary for the UI's creation - this.runInfo = this.scene.gameData.parseSessionData(JSON.stringify(run.entry)); - this.isVictory = run.isVictory; + this.pageMode = RunInfoUiMode.MAIN; // Creates Header and adds to this.runContainer @@ -99,20 +115,24 @@ export default class RunInfoUiHandler extends UiHandler { // Creates Run Result Container this.runResultContainer = this.scene.add.container(0, 24); - const runResultWindow = addWindow(this.scene, 0, 0, this.statsBgWidth-11, 65); + const runResultWindow = addWindow(this.scene, 0, 0, this.statsBgWidth - 11, 65); runResultWindow.setOrigin(0, 0); this.runResultContainer.add(runResultWindow); - this.parseRunResult(); + if (this.runDisplayMode === RunDisplayMode.RUN_HISTORY) { + this.parseRunResult(); + } else if (this.runDisplayMode === RunDisplayMode.SESSION_PREVIEW) { + this.parseRunStatus(); + } // Creates Run Info Container this.runInfoContainer = this.scene.add.container(0, 89); - const runInfoWindow = addWindow(this.scene, 0, 0, this.statsBgWidth-11, 90); + const runInfoWindow = addWindow(this.scene, 0, 0, this.statsBgWidth - 11, 90); const runInfoWindowCoords = runInfoWindow.getBottomRight(); this.runInfoContainer.add(runInfoWindow); this.parseRunInfo(runInfoWindowCoords.x, runInfoWindowCoords.y); // Creates Player Party Container - this.partyContainer = this.scene.add.container(this.statsBgWidth-10, 23); + this.partyContainer = this.scene.add.container(this.statsBgWidth - 10, 23); this.parsePartyInfo(); this.showParty(true); @@ -147,7 +167,7 @@ export default class RunInfoUiHandler extends UiHandler { if (this.runInfo.modifiers.length !== 0) { const headerBgCoords = headerBg.getTopRight(); const abilityButtonContainer = this.scene.add.container(0, 0); - const abilityButtonText = addTextObject(this.scene, 8, 0, i18next.t("runHistory:viewHeldItems"), TextStyle.WINDOW, {fontSize:"34px"}); + const abilityButtonText = addTextObject(this.scene, 8, 0, i18next.t("runHistory:viewHeldItems"), TextStyle.WINDOW, { fontSize:"34px" }); const gamepadType = this.getUi().getGamepadType(); let abilityButtonElement: Phaser.GameObjects.Sprite; if (gamepadType === "touch") { @@ -155,7 +175,7 @@ export default class RunInfoUiHandler extends UiHandler { } else { abilityButtonElement = new Phaser.GameObjects.Sprite(this.scene, 0, 2, gamepadType, this.scene.inputController?.getIconForLatestInputRecorded(SettingKeyboard.Button_Cycle_Ability)); } - abilityButtonContainer.add([abilityButtonText, abilityButtonElement]); + abilityButtonContainer.add([ abilityButtonText, abilityButtonElement ]); abilityButtonContainer.setPosition(headerBgCoords.x - abilityButtonText.displayWidth - abilityButtonElement.displayWidth - 8, 10); this.runContainer.add(abilityButtonContainer); } @@ -178,12 +198,12 @@ export default class RunInfoUiHandler extends UiHandler { const genderStr = PlayerGender[genderIndex]; const runResultTextStyle = this.isVictory ? TextStyle.PERFECT_IV : TextStyle.SUMMARY_RED; const runResultTitle = this.isVictory ? i18next.t("runHistory:victory") : i18next.t("runHistory:defeated", { context: genderStr }); - const runResultText = addTextObject(this.scene, 6, 5, `${runResultTitle} - ${i18next.t("saveSlotSelectUiHandler:wave")} ${this.runInfo.waveIndex}`, runResultTextStyle, {fontSize : "65px", lineSpacing: 0.1}); + const runResultText = addTextObject(this.scene, 6, 5, `${runResultTitle} - ${i18next.t("saveSlotSelectUiHandler:wave")} ${this.runInfo.waveIndex}`, runResultTextStyle, { fontSize : "65px", lineSpacing: 0.1 }); if (this.isVictory) { const hallofFameInstructionContainer = this.scene.add.container(0, 0); - const shinyButtonText = addTextObject(this.scene, 8, 0, i18next.t("runHistory:viewHallOfFame"), TextStyle.WINDOW, {fontSize:"65px"}); - const formButtonText = addTextObject(this.scene, 8, 12, i18next.t("runHistory:viewEndingSplash"), TextStyle.WINDOW, {fontSize:"65px"}); + const shinyButtonText = addTextObject(this.scene, 8, 0, i18next.t("runHistory:viewHallOfFame"), TextStyle.WINDOW, { fontSize:"65px" }); + const formButtonText = addTextObject(this.scene, 8, 12, i18next.t("runHistory:viewEndingSplash"), TextStyle.WINDOW, { fontSize:"65px" }); const gamepadType = this.getUi().getGamepadType(); let shinyButtonElement: Phaser.GameObjects.Sprite; let formButtonElement: Phaser.GameObjects.Sprite; @@ -194,9 +214,9 @@ export default class RunInfoUiHandler extends UiHandler { shinyButtonElement = new Phaser.GameObjects.Sprite(this.scene, 0, 4, gamepadType, this.scene.inputController?.getIconForLatestInputRecorded(SettingKeyboard.Button_Cycle_Shiny)); formButtonElement = new Phaser.GameObjects.Sprite(this.scene, 0, 16, gamepadType, this.scene.inputController?.getIconForLatestInputRecorded(SettingKeyboard.Button_Cycle_Form)); } - hallofFameInstructionContainer.add([shinyButtonText, shinyButtonElement]); + hallofFameInstructionContainer.add([ shinyButtonText, shinyButtonElement ]); - hallofFameInstructionContainer.add([formButtonText, formButtonElement]); + hallofFameInstructionContainer.add([ formButtonText, formButtonElement ]); hallofFameInstructionContainer.setPosition(12, 25); this.runResultContainer.add(hallofFameInstructionContainer); @@ -209,14 +229,14 @@ export default class RunInfoUiHandler extends UiHandler { // Wild - Single and Doubles if (this.runInfo.battleType === BattleType.WILD || (this.runInfo.battleType === BattleType.MYSTERY_ENCOUNTER && !this.runInfo.trainer)) { switch (this.runInfo.enemyParty.length) { - case 1: + case 1: // Wild - Singles - this.parseWildSingleDefeat(enemyContainer); - break; - case 2: + this.parseWildSingleDefeat(enemyContainer); + break; + case 2: //Wild - Doubles - this.parseWildDoubleDefeat(enemyContainer); - break; + this.parseWildDoubleDefeat(enemyContainer); + break; } } else if (this.runInfo.battleType === BattleType.TRAINER || (this.runInfo.battleType === BattleType.MYSTERY_ENCOUNTER && this.runInfo.trainer)) { this.parseTrainerDefeat(enemyContainer); @@ -226,6 +246,66 @@ export default class RunInfoUiHandler extends UiHandler { this.runContainer.add(this.runResultContainer); } + /** + * This function is used when the Run Info UI is used to preview a Session. + * It edits {@linkcode runResultContainer}, but most importantly - does not display the negative results of a Mystery Encounter or any details of a trainer's party. + * Trainer Parties are replaced with their sprites, names, and their party size. + * Mystery Encounters contain sprites associated with MEs + the title of the specific ME. + */ + private parseRunStatus() { + const runStatusText = addTextObject(this.scene, 6, 5, `${i18next.t("saveSlotSelectUiHandler:wave")} ${this.runInfo.waveIndex} - ${getBiomeName(this.runInfo.arena.biome)}`, TextStyle.WINDOW, { fontSize : "65px", lineSpacing: 0.1 }); + + const enemyContainer = this.scene.add.container(0, 0); + this.runResultContainer.add(enemyContainer); + if (this.runInfo.battleType === BattleType.WILD) { + if (this.runInfo.enemyParty.length === 1) { + this.parseWildSingleDefeat(enemyContainer); + } else if (this.runInfo.enemyParty.length === 2) { + this.parseWildDoubleDefeat(enemyContainer); + } + } else if (this.runInfo.battleType === BattleType.TRAINER) { + this.showTrainerSprites(enemyContainer); + const row_limit = 3; + this.runInfo.enemyParty.forEach((p, i) => { + const pokeball = this.scene.add.sprite(0, 0, "pb"); + pokeball.setFrame(getPokeballAtlasKey(p.pokeball)); + pokeball.setScale(0.5); + pokeball.setPosition(52 + ((i % row_limit) * 8), (i <= 2) ? 18 : 25); + enemyContainer.add(pokeball); + }); + const trainerObj = this.runInfo.trainer.toTrainer(this.scene); + const RIVAL_TRAINER_ID_THRESHOLD = 375; + let trainerName = ""; + if (this.runInfo.trainer.trainerType >= RIVAL_TRAINER_ID_THRESHOLD) { + trainerName = (trainerObj.variant === TrainerVariant.FEMALE) ? i18next.t("trainerNames:rival_female") : i18next.t("trainerNames:rival"); + } else { + trainerName = trainerObj.getName(0, true); + } + const boxString = i18next.t(trainerObj.variant !== TrainerVariant.DOUBLE ? "battle:trainerAppeared" : "battle:trainerAppearedDouble", { trainerName: trainerName }).replace(/\n/g, " "); + const descContainer = this.scene.add.container(0, 0); + const textBox = addTextObject(this.scene, 0, 0, boxString, TextStyle.WINDOW, { fontSize : "35px", wordWrap: { width: 200 }}); + descContainer.add(textBox); + descContainer.setPosition(52, 29); + this.runResultContainer.add(descContainer); + } else if (this.runInfo.battleType === BattleType.MYSTERY_ENCOUNTER) { + const encounterExclaim = this.scene.add.sprite(0, 0, "encounter_exclaim"); + encounterExclaim.setPosition(34, 26); + encounterExclaim.setScale(0.65); + const subSprite = this.scene.add.sprite(56, -106, "pkmn__sub"); + subSprite.setScale(0.65); + subSprite.setPosition(34, 46); + const mysteryEncounterTitle = i18next.t(this.scene.getMysteryEncounter(this.runInfo.mysteryEncounterType as MysteryEncounterType, true).localizationKey + ":title"); + const descContainer = this.scene.add.container(0, 0); + const textBox = addTextObject(this.scene, 0, 0, mysteryEncounterTitle, TextStyle.WINDOW, { fontSize : "45px", wordWrap: { width: 160 }}); + descContainer.add(textBox); + descContainer.setPosition(47, 37); + this.runResultContainer.add([ encounterExclaim, subSprite, descContainer ]); + } + + this.runResultContainer.add(runStatusText); + this.runContainer.add(this.runResultContainer); + } + /** * This function is called to edit an enemyContainer to represent a loss from a defeat by a wild single Pokemon battle. * @param enemyContainer - container holding enemy visual and level information @@ -270,7 +350,7 @@ export default class RunInfoUiHandler extends UiHandler { enemyLevel.setOrigin(1, 0); enemyIconContainer.add(enemyIcon); enemyIconContainer.add(enemyLevel); - enemyIconContainer.setPosition(e*35, 0); + enemyIconContainer.setPosition(e * 35, 0); enemyContainer.add(enemyIconContainer); enemy.destroy(); }); @@ -278,40 +358,58 @@ export default class RunInfoUiHandler extends UiHandler { } /** - * This edits a container to represent a loss from a defeat by a trainer battle. - * @param enemyContainer - container holding enemy visuals and level information - * The trainers are placed to the left of their party. - * Depending on the trainer icon, there may be overlap between the edges of the box or their party. (Capes...) - * - * Party Pokemon have their icons, terastalization status, and level shown. + * This loads the enemy sprites, positions, and scales them according to the current display mode of the RunInfo UI and then adds them to the container parameter. + * Used by {@linkcode parseRunStatus} and {@linkcode parseTrainerDefeat} + * @param enemyContainer a Phaser Container that should hold enemy sprites */ - private parseTrainerDefeat(enemyContainer: Phaser.GameObjects.Container) { + private showTrainerSprites(enemyContainer: Phaser.GameObjects.Container) { // Creating the trainer sprite and adding it to enemyContainer const tObj = this.runInfo.trainer.toTrainer(this.scene); - // Loads trainer assets on demand, as they are not loaded by default in the scene tObj.config.loadAssets(this.scene, this.runInfo.trainer.variant).then(() => { const tObjSpriteKey = tObj.config.getSpriteKey(this.runInfo.trainer.variant === TrainerVariant.FEMALE, false); const tObjSprite = this.scene.add.sprite(0, 5, tObjSpriteKey); - if (this.runInfo.trainer.variant === TrainerVariant.DOUBLE) { + if (this.runInfo.trainer.variant === TrainerVariant.DOUBLE && !tObj.config.doubleOnly) { const doubleContainer = this.scene.add.container(5, 8); tObjSprite.setPosition(-3, -3); const tObjPartnerSpriteKey = tObj.config.getSpriteKey(true, true); const tObjPartnerSprite = this.scene.add.sprite(5, -3, tObjPartnerSpriteKey); // Double Trainers have smaller sprites than Single Trainers - tObjPartnerSprite.setScale(0.20); - tObjSprite.setScale(0.20); - doubleContainer.add(tObjSprite); - doubleContainer.add(tObjPartnerSprite); - doubleContainer.setPosition(12, 38); + if (this.runDisplayMode === RunDisplayMode.RUN_HISTORY) { + tObjPartnerSprite.setScale(0.20); + tObjSprite.setScale(0.20); + doubleContainer.add(tObjSprite); + doubleContainer.add(tObjPartnerSprite); + doubleContainer.setPosition(12, 38); + } else { + tObjSprite.setScale(0.55); + tObjSprite.setPosition(-9, -3); + tObjPartnerSprite.setScale(0.55); + doubleContainer.add([ tObjSprite, tObjPartnerSprite ]); + doubleContainer.setPosition(28, 40); + } enemyContainer.add(doubleContainer); } else { - tObjSprite.setScale(0.35, 0.35); - tObjSprite.setPosition(12, 28); + const scale = (this.runDisplayMode === RunDisplayMode.RUN_HISTORY) ? 0.35 : 0.65; + const position = (this.runDisplayMode === RunDisplayMode.RUN_HISTORY) ? [ 12, 28 ] : [ 32, 36 ]; + tObjSprite.setScale(scale, scale); + tObjSprite.setPosition(position[0], position[1]); enemyContainer.add(tObjSprite); } }); + } + /** + * This edits a container to represent a loss from a defeat by a trainer battle. + * The trainers are placed to the left of their party. + * Depending on the trainer icon, there may be overlap between the edges of the box or their party. (Capes...) + * + * Party Pokemon have their icons, terastalization status, and level shown. + * @param enemyContainer - container holding enemy visuals and level information + */ + private parseTrainerDefeat(enemyContainer: Phaser.GameObjects.Container) { + // Loads and adds trainer sprites to the UI + this.showTrainerSprites(enemyContainer); // Determining which Terastallize Modifier belongs to which Pokemon // Creates a dictionary {PokemonId: TeraShardType} const teraPokemon = {}; @@ -328,7 +426,7 @@ export default class RunInfoUiHandler extends UiHandler { // 2 Rows x 3 Columns const enemyPartyContainer = this.scene.add.container(0, 0); this.runInfo.enemyParty.forEach((enemyData, e) => { - const pokemonRowHeight = Math.floor(e/3); + const pokemonRowHeight = Math.floor(e / 3); const enemyIconContainer = this.scene.add.container(0, 0); enemyIconContainer.setScale(0.6); const isBoss = enemyData.boss; @@ -348,8 +446,8 @@ export default class RunInfoUiHandler extends UiHandler { enemySprite2.setTint(teraColor.color); } } - enemyIcon.setPosition(39*(e%3)+5, (35*pokemonRowHeight)); - const enemyLevel = addTextObject(this.scene, 43*(e%3), (27*(pokemonRowHeight+1)), `${i18next.t("saveSlotSelectUiHandler:lv")}${Utils.formatLargeNumber(enemy.level, 1000)}`, isBoss ? TextStyle.PARTY_RED : TextStyle.PARTY, { fontSize: "54px" }); + enemyIcon.setPosition(39 * (e % 3) + 5, (35 * pokemonRowHeight)); + const enemyLevel = addTextObject(this.scene, 43 * (e % 3), (27 * (pokemonRowHeight + 1)), `${i18next.t("saveSlotSelectUiHandler:lv")}${Utils.formatLargeNumber(enemy.level, 1000)}`, isBoss ? TextStyle.PARTY_RED : TextStyle.PARTY, { fontSize: "54px" }); enemyLevel.setShadow(0, 0, undefined); enemyLevel.setStroke("#424242", 14); enemyLevel.setOrigin(0, 0); @@ -372,37 +470,37 @@ export default class RunInfoUiHandler extends UiHandler { private async parseRunInfo(windowX: number, windowY: number) { // Parsing and displaying the mode. // In the future, parsing Challenges + Challenge Rules may have to be reworked as PokeRogue adds additional challenges and users can stack these challenges in various ways. - const modeText = addBBCodeTextObject(this.scene, 7, 0, "", TextStyle.WINDOW, {fontSize : "50px", lineSpacing:3}); + const modeText = addBBCodeTextObject(this.scene, 7, 0, "", TextStyle.WINDOW, { fontSize : "50px", lineSpacing:3 }); modeText.setPosition(7, 5); - modeText.appendText(i18next.t("runHistory:mode")+": ", false); + modeText.appendText(i18next.t("runHistory:mode") + ": ", false); switch (this.runInfo.gameMode) { - case GameModes.DAILY: - modeText.appendText(`${i18next.t("gameMode:dailyRun")}`, false); - break; - case GameModes.SPLICED_ENDLESS: - modeText.appendText(`${i18next.t("gameMode:endlessSpliced")}`, false); - break; - case GameModes.CHALLENGE: - modeText.appendText(`${i18next.t("gameMode:challenge")}`, false); - modeText.appendText(`${i18next.t("runHistory:challengeRules")}: `); - modeText.setWrapMode(1); // wrap by word - modeText.setWrapWidth(500); - const rules: string[] = this.challengeParser(); - if (rules) { - for (let i = 0; i < rules.length; i++) { - if (i > 0) { - modeText.appendText(" + ", false); + case GameModes.DAILY: + modeText.appendText(`${i18next.t("gameMode:dailyRun")}`, false); + break; + case GameModes.SPLICED_ENDLESS: + modeText.appendText(`${i18next.t("gameMode:endlessSpliced")}`, false); + break; + case GameModes.CHALLENGE: + modeText.appendText(`${i18next.t("gameMode:challenge")}`, false); + modeText.appendText(`${i18next.t("runHistory:challengeRules")}: `); + modeText.setWrapMode(1); // wrap by word + modeText.setWrapWidth(500); + const rules: string[] = this.challengeParser(); + if (rules) { + for (let i = 0; i < rules.length; i++) { + if (i > 0) { + modeText.appendText(" + ", false); + } + modeText.appendText(rules[i], false); } - modeText.appendText(rules[i], false); } - } - break; - case GameModes.ENDLESS: - modeText.appendText(`${i18next.t("gameMode:endless")}`, false); - break; - case GameModes.CLASSIC: - modeText.appendText(`${i18next.t("gameMode:classic")}`, false); - break; + break; + case GameModes.ENDLESS: + modeText.appendText(`${i18next.t("gameMode:endless")}`, false); + break; + case GameModes.CLASSIC: + modeText.appendText(`${i18next.t("gameMode:classic")}`, false); + break; } // If the player achieves a personal best in Endless, the mode text will be tinted similarly to SSS luck to celebrate their achievement. @@ -415,25 +513,25 @@ export default class RunInfoUiHandler extends UiHandler { const runInfoTextContainer = this.scene.add.container(0, 0); // Japanese is set to a greater line spacing of 35px in addBBCodeTextObject() if lineSpacing < 12. const lineSpacing = (i18next.resolvedLanguage === "ja") ? 12 : 3; - const runInfoText = addBBCodeTextObject(this.scene, 7, 0, "", TextStyle.WINDOW, {fontSize: "50px", lineSpacing: lineSpacing}); + const runInfoText = addBBCodeTextObject(this.scene, 7, 0, "", TextStyle.WINDOW, { fontSize: "50px", lineSpacing: lineSpacing }); const runTime = Utils.getPlayTimeString(this.runInfo.playTime); runInfoText.appendText(`${i18next.t("runHistory:runLength")}: ${runTime}`, false); const runMoney = Utils.formatMoney(this.scene.moneyFormat, this.runInfo.money); - runInfoText.appendText(`[color=${getTextColor(TextStyle.MONEY)}]${i18next.t("battleScene:moneyOwned", {formattedMoney : runMoney})}[/color]`); + runInfoText.appendText(`[color=${getTextColor(TextStyle.MONEY)}]${i18next.t("battleScene:moneyOwned", { formattedMoney : runMoney })}[/color]`); runInfoText.setPosition(7, 70); runInfoTextContainer.add(runInfoText); // Luck // Uses the parameters windowX and windowY to dynamically position the luck value neatly into the bottom right corner - const luckText = addBBCodeTextObject(this.scene, 0, 0, "", TextStyle.WINDOW, {fontSize: "55px"}); + const luckText = addBBCodeTextObject(this.scene, 0, 0, "", TextStyle.WINDOW, { fontSize: "55px" }); const luckValue = Phaser.Math.Clamp(this.runInfo.party.map(p => p.toPokemon(this.scene).getLuck()).reduce((total: integer, value: integer) => total += value, 0), 0, 14); - let luckInfo = i18next.t("runHistory:luck")+": "+getLuckString(luckValue); + let luckInfo = i18next.t("runHistory:luck") + ": " + getLuckString(luckValue); if (luckValue < 14) { - luckInfo = "[color=#"+(getLuckTextTint(luckValue)).toString(16)+"]"+luckInfo+"[/color]"; + luckInfo = "[color=#" + (getLuckTextTint(luckValue)).toString(16) + "]" + luckInfo + "[/color]"; } else { luckText.setTint(0xffef5c, 0x47ff69, 0x6b6bff, 0xff6969); } - luckText.appendText("[align=right]"+luckInfo+"[/align]", false); - luckText.setPosition(windowX-luckText.displayWidth-5, windowY-13); + luckText.appendText("[align=right]" + luckInfo + "[/align]", false); + luckText.setPosition(windowX - luckText.displayWidth - 5, windowY - 13); runInfoTextContainer.add(luckText); // Player Held Items @@ -450,8 +548,8 @@ export default class RunInfoUiHandler extends UiHandler { } const icon = modifier?.getIcon(this.scene, false); if (icon) { - const rowHeightModifier = Math.floor(visibleModifierIndex/7); - icon.setPosition(24 * (visibleModifierIndex%7), 20 + (35 * rowHeightModifier)); + const rowHeightModifier = Math.floor(visibleModifierIndex / 7); + icon.setPosition(24 * (visibleModifierIndex % 7), 20 + (35 * rowHeightModifier)); modifierIconsContainer.add(icon); } @@ -479,23 +577,23 @@ export default class RunInfoUiHandler extends UiHandler { for (let i = 0; i < this.runInfo.challenges.length; i++) { if (this.runInfo.challenges[i].value !== 0) { switch (this.runInfo.challenges[i].id) { - case Challenges.SINGLE_GENERATION: - rules.push(i18next.t(`runHistory:challengeMonoGen${this.runInfo.challenges[i].value}`)); - break; - case Challenges.SINGLE_TYPE: - const typeRule = Type[this.runInfo.challenges[i].value-1]; - const typeTextColor = `[color=${TypeColor[typeRule]}]`; - const typeShadowColor = `[shadow=${TypeShadow[typeRule]}]`; - const typeText = typeTextColor + typeShadowColor + i18next.t(`pokemonInfo:Type.${typeRule}`)!+"[/color]"+"[/shadow]"; - rules.push(typeText); - break; - case Challenges.FRESH_START: - rules.push(i18next.t("challenges:freshStart.name")); - break; - case Challenges.INVERSE_BATTLE: - // - rules.push(i18next.t("challenges:inverseBattle.shortName")); - break; + case Challenges.SINGLE_GENERATION: + rules.push(i18next.t(`runHistory:challengeMonoGen${this.runInfo.challenges[i].value}`)); + break; + case Challenges.SINGLE_TYPE: + const typeRule = Type[this.runInfo.challenges[i].value - 1]; + const typeTextColor = `[color=${TypeColor[typeRule]}]`; + const typeShadowColor = `[shadow=${TypeShadow[typeRule]}]`; + const typeText = typeTextColor + typeShadowColor + i18next.t(`pokemonInfo:Type.${typeRule}`)! + "[/color]" + "[/shadow]"; + rules.push(typeText); + break; + case Challenges.INVERSE_BATTLE: + rules.push(i18next.t("challenges:inverseBattle.shortName")); + break; + default: + const localisationKey = Challenges[this.runInfo.challenges[i].id].split("_").map((f, i) => i ? `${f[0]}${f.slice(1).toLowerCase()}` : f.toLowerCase()).join(""); + rules.push(i18next.t(`challenges:${localisationKey}.name`)); + break; } } } @@ -510,13 +608,13 @@ export default class RunInfoUiHandler extends UiHandler { private parsePartyInfo(): void { const party = this.runInfo.party; const currentLanguage = i18next.resolvedLanguage ?? "en"; - const windowHeight = ((this.scene.game.canvas.height / 6) - 23)/6; + const windowHeight = ((this.scene.game.canvas.height / 6) - 23) / 6; party.forEach((p: PokemonData, i: integer) => { - const pokemonInfoWindow = new RoundRectangle(this.scene, 0, 14, (this.statsBgWidth*2)+10, windowHeight-2, 3); + const pokemonInfoWindow = new RoundRectangle(this.scene, 0, 14, (this.statsBgWidth * 2) + 10, windowHeight - 2, 3); const pokemon = p.toPokemon(this.scene); - const pokemonInfoContainer = this.scene.add.container(this.statsBgWidth+5, (windowHeight-0.5)*i); + const pokemonInfoContainer = this.scene.add.container(this.statsBgWidth + 5, (windowHeight - 0.5) * i); const types = pokemon.getTypes(); const type1 = getTypeRgb(types[0]); @@ -544,18 +642,18 @@ export default class RunInfoUiHandler extends UiHandler { const pName = pokemon.getNameToRender(); //With the exception of Korean/Traditional Chinese/Simplified Chinese, the code shortens the terms for ability and passive to their first letter. //These languages are exempted because they are already short enough. - const exemptedLanguages = ["ko", "zh_CN", "zh_TW"]; + const exemptedLanguages = [ "ko", "zh_CN", "zh_TW" ]; let passiveLabel = i18next.t("starterSelectUiHandler:passive") ?? "-"; let abilityLabel = i18next.t("starterSelectUiHandler:ability") ?? "-"; if (!exemptedLanguages.includes(currentLanguage)) { passiveLabel = passiveLabel.charAt(0); abilityLabel = abilityLabel.charAt(0); } - const pPassiveInfo = pokemon.passive ? passiveLabel+": "+pokemon.getPassiveAbility().name : ""; + const pPassiveInfo = pokemon.passive ? passiveLabel + ": " + pokemon.getPassiveAbility().name : ""; const pAbilityInfo = abilityLabel + ": " + pokemon.getAbility().name; // Japanese is set to a greater line spacing of 35px in addBBCodeTextObject() if lineSpacing < 12. const lineSpacing = (i18next.resolvedLanguage === "ja") ? 12 : 3; - const pokeInfoText = addBBCodeTextObject(this.scene, 0, 0, pName, TextStyle.SUMMARY, {fontSize: textContainerFontSize, lineSpacing: lineSpacing}); + const pokeInfoText = addBBCodeTextObject(this.scene, 0, 0, pName, TextStyle.SUMMARY, { fontSize: textContainerFontSize, lineSpacing: lineSpacing }); pokeInfoText.appendText(`${i18next.t("saveSlotSelectUiHandler:lv")}${Utils.formatFancyLargeNumber(pokemon.level, 1)} - ${pNatureName}`); pokeInfoText.appendText(pAbilityInfo); pokeInfoText.appendText(pPassiveInfo); @@ -564,27 +662,27 @@ export default class RunInfoUiHandler extends UiHandler { // Pokemon Stats // Colored Arrows (Red/Blue) are placed by stats that are boosted from natures const pokeStatTextContainer = this.scene.add.container(-35, 6); - const pStats : string[]= []; + const pStats : string[] = []; pokemon.stats.forEach((element) => pStats.push(Utils.formatFancyLargeNumber(element, 1))); for (let i = 0; i < pStats.length; i++) { const isMult = getNatureStatMultiplier(pNature, i); pStats[i] = (isMult < 1) ? pStats[i] + "[color=#40c8f8]↓[/color]" : pStats[i]; pStats[i] = (isMult > 1) ? pStats[i] + "[color=#f89890]↑[/color]" : pStats[i]; } - const hp = i18next.t("pokemonInfo:Stat.HPshortened")+": "+pStats[0]; - const atk = i18next.t("pokemonInfo:Stat.ATKshortened")+": "+pStats[1]; - const def = i18next.t("pokemonInfo:Stat.DEFshortened")+": "+pStats[2]; - const spatk = i18next.t("pokemonInfo:Stat.SPATKshortened")+": "+pStats[3]; - const spdef = i18next.t("pokemonInfo:Stat.SPDEFshortened")+": "+pStats[4]; - const speedLabel = (currentLanguage==="es"||currentLanguage==="pt_BR") ? i18next.t("runHistory:SPDshortened") : i18next.t("pokemonInfo:Stat.SPDshortened"); - const speed = speedLabel+": "+pStats[5]; + const hp = i18next.t("pokemonInfo:Stat.HPshortened") + ": " + pStats[0]; + const atk = i18next.t("pokemonInfo:Stat.ATKshortened") + ": " + pStats[1]; + const def = i18next.t("pokemonInfo:Stat.DEFshortened") + ": " + pStats[2]; + const spatk = i18next.t("pokemonInfo:Stat.SPATKshortened") + ": " + pStats[3]; + const spdef = i18next.t("pokemonInfo:Stat.SPDEFshortened") + ": " + pStats[4]; + const speedLabel = (currentLanguage === "es" || currentLanguage === "pt_BR") ? i18next.t("runHistory:SPDshortened") : i18next.t("pokemonInfo:Stat.SPDshortened"); + const speed = speedLabel + ": " + pStats[5]; // Column 1: HP Atk Def - const pokeStatText1 = addBBCodeTextObject(this.scene, -5, 0, hp, TextStyle.SUMMARY, {fontSize: textContainerFontSize, lineSpacing: lineSpacing}); + const pokeStatText1 = addBBCodeTextObject(this.scene, -5, 0, hp, TextStyle.SUMMARY, { fontSize: textContainerFontSize, lineSpacing: lineSpacing }); pokeStatText1.appendText(atk); pokeStatText1.appendText(def); pokeStatTextContainer.add(pokeStatText1); // Column 2: SpAtk SpDef Speed - const pokeStatText2 = addBBCodeTextObject(this.scene, 25, 0, spatk, TextStyle.SUMMARY, {fontSize: textContainerFontSize, lineSpacing: lineSpacing}); + const pokeStatText2 = addBBCodeTextObject(this.scene, 25, 0, spatk, TextStyle.SUMMARY, { fontSize: textContainerFontSize, lineSpacing: lineSpacing }); pokeStatText2.appendText(spdef); pokeStatText2.appendText(speed); pokeStatTextContainer.add(pokeStatText2); @@ -612,7 +710,7 @@ export default class RunInfoUiHandler extends UiHandler { const fusionShinyStar = this.scene.add.image(0, 0, "shiny_star_small_2"); fusionShinyStar.setOrigin(0, 0); fusionShinyStar.setScale(0.5); - fusionShinyStar.setPosition(shinyStar.x+1, shinyStar.y+1); + fusionShinyStar.setPosition(shinyStar.x + 1, shinyStar.y + 1); fusionShinyStar.setTint(getVariantTint(pokemon.fusionVariant)); marksContainer.add(fusionShinyStar); this.getUi().bringToTop(fusionShinyStar); @@ -625,7 +723,7 @@ export default class RunInfoUiHandler extends UiHandler { const movesetContainer = this.scene.add.container(70, -29); const pokemonMoveBgs : Phaser.GameObjects.NineSlice[] = []; const pokemonMoveLabels : Phaser.GameObjects.Text[] = []; - const movePos = [[-6.5, 35.5], [37, 35.5], [-6.5, 43.5], [37, 43.5]]; + const movePos = [[ -6.5, 35.5 ], [ 37, 35.5 ], [ -6.5, 43.5 ], [ 37, 43.5 ]]; for (let m = 0; m < pokemonMoveset?.length; m++) { const moveContainer = this.scene.add.container(movePos[m][0], movePos[m][1]); moveContainer.setScale(0.5); @@ -660,7 +758,7 @@ export default class RunInfoUiHandler extends UiHandler { if (heldItemsList.length > 0) { (heldItemsList as Modifier.PokemonHeldItemModifier[]).sort(Modifier.modifierSortFunc); let row = 0; - for (const [index, item] of heldItemsList.entries()) { + for (const [ index, item ] of heldItemsList.entries()) { if ( index > 36 ) { const overflowIcon = addTextObject(this.scene, 182, 4, "+", TextStyle.WINDOW); heldItemsContainer.add(overflowIcon); @@ -671,7 +769,7 @@ export default class RunInfoUiHandler extends UiHandler { itemIcon.list[1].clearTint(); } itemIcon.setScale(heldItemsScale); - itemIcon.setPosition((index%19) * 10, row * 10); + itemIcon.setPosition((index % 19) * 10, row * 10); heldItemsContainer.add(itemIcon); if (index !== 0 && index % 18 === 0) { row++; @@ -754,15 +852,15 @@ export default class RunInfoUiHandler extends UiHandler { endCard.setScale(0.5); const endCardCoords = endCard.getBottomCenter(); const overlayColor = isFemale ? "red" : "blue"; - const hallofFameBg = this.scene.add.image(0, 0, "hall_of_fame_"+overlayColor); + const hallofFameBg = this.scene.add.image(0, 0, "hall_of_fame_" + overlayColor); hallofFameBg.setPosition(159, 89); - hallofFameBg.setSize(this.scene.game.canvas.width, this.scene.game.canvas.height+10); + hallofFameBg.setSize(this.scene.game.canvas.width, this.scene.game.canvas.height + 10); hallofFameBg.setAlpha(0.8); this.hallofFameContainer.add(endCard); this.hallofFameContainer.add(hallofFameBg); const hallofFameText = addTextObject(this.scene, 0, 0, i18next.t("runHistory:hallofFameText", { context: genderStr }), TextStyle.WINDOW); - hallofFameText.setPosition(endCardCoords.x-(hallofFameText.displayWidth/2), 164); + hallofFameText.setPosition(endCardCoords.x - (hallofFameText.displayWidth / 2), 164); this.hallofFameContainer.add(hallofFameText); this.runInfo.party.forEach((p, i) => { const pkmn = p.toPokemon(this.scene); @@ -813,36 +911,36 @@ export default class RunInfoUiHandler extends UiHandler { const error = false; switch (button) { - case Button.CANCEL: - success = true; - if (this.pageMode === RunInfoUiMode.MAIN) { - this.runInfoContainer.removeAll(true); - this.runResultContainer.removeAll(true); - this.partyContainer.removeAll(true); - this.runContainer.removeAll(true); - if (this.isVictory) { - this.hallofFameContainer.removeAll(true); + case Button.CANCEL: + success = true; + if (this.pageMode === RunInfoUiMode.MAIN) { + this.runInfoContainer.removeAll(true); + this.runResultContainer.removeAll(true); + this.partyContainer.removeAll(true); + this.runContainer.removeAll(true); + if (this.isVictory) { + this.hallofFameContainer.removeAll(true); + } + super.clear(); + this.runContainer.setVisible(false); + ui.revertMode(); + } else if (this.pageMode === RunInfoUiMode.HALL_OF_FAME) { + this.hallofFameContainer.setVisible(false); + this.pageMode = RunInfoUiMode.MAIN; + } else if (this.pageMode === RunInfoUiMode.ENDING_ART) { + this.endCardContainer.setVisible(false); + this.runContainer.remove(this.endCardContainer); + this.pageMode = RunInfoUiMode.MAIN; } - super.clear(); - this.runContainer.setVisible(false); - ui.revertMode(); - } else if (this.pageMode === RunInfoUiMode.HALL_OF_FAME) { - this.hallofFameContainer.setVisible(false); - this.pageMode = RunInfoUiMode.MAIN; - } else if (this.pageMode === RunInfoUiMode.ENDING_ART) { - this.endCardContainer.setVisible(false); - this.runContainer.remove(this.endCardContainer); - this.pageMode = RunInfoUiMode.MAIN; - } - break; - case Button.DOWN: - case Button.UP: - break; - case Button.CYCLE_FORM: - case Button.CYCLE_SHINY: - case Button.CYCLE_ABILITY: - this.buttonCycleOption(button); - break; + break; + case Button.DOWN: + case Button.UP: + break; + case Button.CYCLE_FORM: + case Button.CYCLE_SHINY: + case Button.CYCLE_ABILITY: + this.buttonCycleOption(button); + break; } if (success) { @@ -862,40 +960,40 @@ export default class RunInfoUiHandler extends UiHandler { */ private buttonCycleOption(button: Button) { switch (button) { - case Button.CYCLE_FORM: - if (this.isVictory && this.pageMode !== RunInfoUiMode.HALL_OF_FAME) { - if (!this.endCardContainer || !this.endCardContainer.visible) { - this.createVictorySplash(); - this.endCardContainer.setVisible(true); - this.runContainer.add(this.endCardContainer); - this.pageMode = RunInfoUiMode.ENDING_ART; - } else { - this.endCardContainer.setVisible(false); - this.runContainer.remove(this.endCardContainer); - this.pageMode = RunInfoUiMode.MAIN; + case Button.CYCLE_FORM: + if (this.isVictory && this.pageMode !== RunInfoUiMode.HALL_OF_FAME) { + if (!this.endCardContainer || !this.endCardContainer.visible) { + this.createVictorySplash(); + this.endCardContainer.setVisible(true); + this.runContainer.add(this.endCardContainer); + this.pageMode = RunInfoUiMode.ENDING_ART; + } else { + this.endCardContainer.setVisible(false); + this.runContainer.remove(this.endCardContainer); + this.pageMode = RunInfoUiMode.MAIN; + } } - } - break; - case Button.CYCLE_SHINY: - if (this.isVictory && this.pageMode !== RunInfoUiMode.ENDING_ART) { - if (!this.hallofFameContainer.visible) { - this.hallofFameContainer.setVisible(true); - this.pageMode = RunInfoUiMode.HALL_OF_FAME; - } else { - this.hallofFameContainer.setVisible(false); - this.pageMode = RunInfoUiMode.MAIN; + break; + case Button.CYCLE_SHINY: + if (this.isVictory && this.pageMode !== RunInfoUiMode.ENDING_ART) { + if (!this.hallofFameContainer.visible) { + this.hallofFameContainer.setVisible(true); + this.pageMode = RunInfoUiMode.HALL_OF_FAME; + } else { + this.hallofFameContainer.setVisible(false); + this.pageMode = RunInfoUiMode.MAIN; + } } - } - break; - case Button.CYCLE_ABILITY: - if (this.runInfo.modifiers.length !== 0 && this.pageMode === RunInfoUiMode.MAIN) { - if (this.partyVisibility) { - this.showParty(false); - } else { - this.showParty(true); + break; + case Button.CYCLE_ABILITY: + if (this.runInfo.modifiers.length !== 0 && this.pageMode === RunInfoUiMode.MAIN) { + if (this.partyVisibility) { + this.showParty(false); + } else { + this.showParty(true); + } } - } - break; + break; } } } diff --git a/src/ui/save-slot-select-ui-handler.ts b/src/ui/save-slot-select-ui-handler.ts index 89b20322a68..7bfecb1f99b 100644 --- a/src/ui/save-slot-select-ui-handler.ts +++ b/src/ui/save-slot-select-ui-handler.ts @@ -10,8 +10,10 @@ import MessageUiHandler from "./message-ui-handler"; import { TextStyle, addTextObject } from "./text"; import { Mode } from "./ui"; import { addWindow } from "./ui-theme"; +import { RunDisplayMode } from "#app/ui/run-info-ui-handler"; -const sessionSlotCount = 5; +const SESSION_SLOTS_COUNT = 5; +const SLOTS_ON_SCREEN = 3; export enum SaveSlotUiMode { LOAD, @@ -33,7 +35,7 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { private scrollCursor: integer = 0; - private cursorObj: Phaser.GameObjects.NineSlice | null; + private cursorObj: Phaser.GameObjects.Container | null; private sessionSlotsContainerInitialY: number; @@ -84,9 +86,9 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { this.saveSlotSelectContainer.setVisible(true); this.populateSessionSlots(); + this.setScrollCursor(0); this.setCursor(0); - return true; } @@ -104,40 +106,40 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { error = true; } else { switch (this.uiMode) { - case SaveSlotUiMode.LOAD: - this.saveSlotSelectCallback = null; - originalCallback && originalCallback(cursor); - break; - case SaveSlotUiMode.SAVE: - const saveAndCallback = () => { - const originalCallback = this.saveSlotSelectCallback; + case SaveSlotUiMode.LOAD: this.saveSlotSelectCallback = null; - ui.revertMode(); - ui.showText("", 0); - ui.setMode(Mode.MESSAGE); originalCallback && originalCallback(cursor); - }; - if (this.sessionSlots[cursor].hasData) { - ui.showText(i18next.t("saveSlotSelectUiHandler:overwriteData"), null, () => { - ui.setOverlayMode(Mode.CONFIRM, () => { - this.scene.gameData.deleteSession(cursor).then(response => { - if (response === false) { - this.scene.reset(true); - } else { - saveAndCallback(); - } - }); - }, () => { - ui.revertMode(); - ui.showText("", 0); - }, false, 0, 19, 2000); - }); - } else if (this.sessionSlots[cursor].hasData === false) { - saveAndCallback(); - } else { - return false; - } - break; + break; + case SaveSlotUiMode.SAVE: + const saveAndCallback = () => { + const originalCallback = this.saveSlotSelectCallback; + this.saveSlotSelectCallback = null; + ui.revertMode(); + ui.showText("", 0); + ui.setMode(Mode.MESSAGE); + originalCallback && originalCallback(cursor); + }; + if (this.sessionSlots[cursor].hasData) { + ui.showText(i18next.t("saveSlotSelectUiHandler:overwriteData"), null, () => { + ui.setOverlayMode(Mode.CONFIRM, () => { + this.scene.gameData.deleteSession(cursor).then(response => { + if (response === false) { + this.scene.reset(true); + } else { + saveAndCallback(); + } + }); + }, () => { + ui.revertMode(); + ui.showText("", 0); + }, false, 0, 19, 2000); + }); + } else if (this.sessionSlots[cursor].hasData === false) { + saveAndCallback(); + } else { + return false; + } + break; } success = true; } @@ -147,21 +149,28 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { success = true; } } else { + const cursorPosition = this.cursor + this.scrollCursor; switch (button) { - case Button.UP: - if (this.cursor) { - success = this.setCursor(this.cursor - 1); - } else if (this.scrollCursor) { - success = this.setScrollCursor(this.scrollCursor - 1); - } - break; - case Button.DOWN: - if (this.cursor < 2) { - success = this.setCursor(this.cursor + 1); - } else if (this.scrollCursor < sessionSlotCount - 3) { - success = this.setScrollCursor(this.scrollCursor + 1); - } - break; + case Button.UP: + if (this.cursor) { + // Check to prevent cursor from accessing a negative index + success = (this.cursor === 0) ? this.setCursor(this.cursor) : this.setCursor(this.cursor - 1, cursorPosition); + } else if (this.scrollCursor) { + success = this.setScrollCursor(this.scrollCursor - 1, cursorPosition); + } + break; + case Button.DOWN: + if (this.cursor < (SLOTS_ON_SCREEN - 1)) { + success = this.setCursor(this.cursor + 1, cursorPosition); + } else if (this.scrollCursor < SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN) { + success = this.setScrollCursor(this.scrollCursor + 1, cursorPosition); + } + break; + case Button.RIGHT: + if (this.sessionSlots[cursorPosition].hasData && this.sessionSlots[cursorPosition].saveData) { + this.scene.ui.setOverlayMode(Mode.RUN_INFO, this.sessionSlots[cursorPosition].saveData, RunDisplayMode.SESSION_PREVIEW); + success = true; + } } } @@ -175,12 +184,18 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { } populateSessionSlots() { - for (let s = 0; s < sessionSlotCount; s++) { + for (let s = 0; s < SESSION_SLOTS_COUNT; s++) { const sessionSlot = new SessionSlot(this.scene, s); - sessionSlot.load(); this.scene.add.existing(sessionSlot); this.sessionSlotsContainer.add(sessionSlot); this.sessionSlots.push(sessionSlot); + sessionSlot.load().then((success) => { + // If the cursor was moved to this slot while the session was loading + // call setCursor again to shift the slot position and show the arrow for save preview + if (success && (this.cursor + this.scrollCursor) === s) { + this.setCursor(s); + } + }); } } @@ -198,25 +213,79 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { this.saveSlotSelectMessageBoxContainer.setVisible(!!text?.length); } - setCursor(cursor: integer): boolean { + /** + * Move the cursor to a new position and update the view accordingly + * @param cursor the new cursor position, between `0` and `SLOTS_ON_SCREEN - 1` + * @param prevSlotIndex index of the previous session occupied by the cursor, between `0` and `SESSION_SLOTS_COUNT - 1` - optional + * @returns `true` if the cursor position has changed | `false` if it has not + */ + override setCursor(cursor: integer, prevSlotIndex?: integer): boolean { const changed = super.setCursor(cursor); if (!this.cursorObj) { - this.cursorObj = this.scene.add.nineslice(0, 0, "select_cursor_highlight_thick", undefined, 296, 44, 6, 6, 6, 6); - this.cursorObj.setOrigin(0, 0); + this.cursorObj = this.scene.add.container(0, 0); + const cursorBox = this.scene.add.nineslice(0, 0, "select_cursor_highlight_thick", undefined, 296, 44, 6, 6, 6, 6); + const rightArrow = this.scene.add.image(0, 0, "cursor"); + rightArrow.setPosition(160, 0); + rightArrow.setName("rightArrow"); + this.cursorObj.add([ cursorBox, rightArrow ]); this.sessionSlotsContainer.add(this.cursorObj); } - this.cursorObj.setPosition(4, 4 + (cursor + this.scrollCursor) * 56); + const cursorPosition = cursor + this.scrollCursor; + const cursorIncrement = cursorPosition * 56; + if (this.sessionSlots[cursorPosition] && this.cursorObj) { + const hasData = this.sessionSlots[cursorPosition].hasData; + // If the session slot lacks session data, it does not move from its default, central position. + // Only session slots with session data will move leftwards and have a visible arrow. + if (!hasData) { + this.cursorObj.setPosition(151, 26 + cursorIncrement); + this.sessionSlots[cursorPosition].setPosition(0, cursorIncrement); + } else { + this.cursorObj.setPosition(145, 26 + cursorIncrement); + this.sessionSlots[cursorPosition].setPosition(-6, cursorIncrement); + } + this.setArrowVisibility(hasData); + } + if (!Utils.isNullOrUndefined(prevSlotIndex)) { + this.revertSessionSlot(prevSlotIndex); + } return changed; } - setScrollCursor(scrollCursor: integer): boolean { + /** + * Helper function that resets the given session slot to its default central position + */ + revertSessionSlot(slotIndex: integer): void { + const sessionSlot = this.sessionSlots[slotIndex]; + if (sessionSlot) { + sessionSlot.setPosition(0, slotIndex * 56); + } + } + + /** + * Helper function that checks if the session slot involved holds data or not + * @param hasData `true` if session slot contains data | 'false' if not + */ + setArrowVisibility(hasData: boolean): void { + if (this.cursorObj) { + const rightArrow = this.cursorObj?.getByName("rightArrow") as Phaser.GameObjects.Image; + rightArrow.setVisible(hasData); + } + } + + /** + * Move the scrolling cursor to a new position and update the view accordingly + * @param scrollCursor the new cursor position, between `0` and `SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN` + * @param prevSlotIndex index of the previous slot occupied by the cursor, between `0` and `SESSION_SLOTS_COUNT-1` - optional + * @returns `true` if the cursor position has changed | `false` if it has not + */ + setScrollCursor(scrollCursor: integer, prevSlotIndex?: integer): boolean { const changed = scrollCursor !== this.scrollCursor; if (changed) { this.scrollCursor = scrollCursor; - this.setCursor(this.cursor); + this.setCursor(this.cursor, prevSlotIndex); this.scene.tweens.add({ targets: this.sessionSlotsContainer, y: this.sessionSlotsContainerInitialY - 56 * scrollCursor, @@ -231,6 +300,7 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler { clear() { super.clear(); this.saveSlotSelectContainer.setVisible(false); + this.setScrollCursor(0); this.eraseCursor(); this.saveSlotSelectCallback = null; this.clearSessionSlots(); @@ -254,6 +324,8 @@ class SessionSlot extends Phaser.GameObjects.Container { public hasData: boolean; private loadingLabel: Phaser.GameObjects.Text; + public saveData: SessionSaveData; + constructor(scene: BattleScene, slotId: integer) { super(scene, 0, slotId * 56); @@ -330,6 +402,10 @@ class SessionSlot extends Phaser.GameObjects.Container { load(): Promise { return new Promise(resolve => { this.scene.gameData.getSession(this.slotId).then(async sessionData => { + // Ignore the results if the view was exited + if (!this.active) { + return; + } if (!sessionData) { this.hasData = false; this.loadingLabel.setText(i18next.t("saveSlotSelectUiHandler:empty")); @@ -337,6 +413,7 @@ class SessionSlot extends Phaser.GameObjects.Container { return; } this.hasData = true; + this.saveData = sessionData; await this.setupWithData(sessionData); resolve(true); }); diff --git a/src/ui/scrollable-grid-handler.ts b/src/ui/scrollable-grid-handler.ts index f96f3c995b7..cced92a2083 100644 --- a/src/ui/scrollable-grid-handler.ts +++ b/src/ui/scrollable-grid-handler.ts @@ -106,48 +106,48 @@ export default class ScrollableGridUiHandler { const itemOffset = this.scrollCursor * this.COLUMNS; const lastVisibleIndex = Math.min(this.totalElements - 1, this.totalElements - maxScrollCursor * this.COLUMNS - 1); switch (button) { - case Button.UP: - if (currentRowIndex > 0) { - success = this.setCursor(this.cursor - this.COLUMNS); - } else if (this.scrollCursor > 0) { - success = this.setScrollCursor(this.scrollCursor - 1); - } else { + case Button.UP: + if (currentRowIndex > 0) { + success = this.setCursor(this.cursor - this.COLUMNS); + } else if (this.scrollCursor > 0) { + success = this.setScrollCursor(this.scrollCursor - 1); + } else { // wrap around to the last row - let newCursor = this.cursor + (onScreenRows - 1) * this.COLUMNS; - if (newCursor > lastVisibleIndex) { - newCursor -= this.COLUMNS; + let newCursor = this.cursor + (onScreenRows - 1) * this.COLUMNS; + if (newCursor > lastVisibleIndex) { + newCursor -= this.COLUMNS; + } + success = this.setScrollCursor(maxScrollCursor, newCursor); } - success = this.setScrollCursor(maxScrollCursor, newCursor); - } - break; - case Button.DOWN: - if (currentRowIndex < onScreenRows - 1) { + break; + case Button.DOWN: + if (currentRowIndex < onScreenRows - 1) { // Go down one row - success = this.setCursor(Math.min(this.cursor + this.COLUMNS, this.totalElements - itemOffset - 1)); - } else if (this.scrollCursor < maxScrollCursor) { + success = this.setCursor(Math.min(this.cursor + this.COLUMNS, this.totalElements - itemOffset - 1)); + } else if (this.scrollCursor < maxScrollCursor) { // Scroll down one row - success = this.setScrollCursor(this.scrollCursor + 1); - } else { + success = this.setScrollCursor(this.scrollCursor + 1); + } else { // Wrap around to the top row - success = this.setScrollCursor(0, this.cursor % this.COLUMNS); - } - break; - case Button.LEFT: - if (currentColumnIndex > 0) { - success = this.setCursor(this.cursor - 1); - } else if (this.scrollCursor === maxScrollCursor && currentRowIndex === onScreenRows - 1) { - success = this.setCursor(lastVisibleIndex); - } else { - success = this.setCursor(this.cursor + this.COLUMNS - 1); - } - break; - case Button.RIGHT: - if (currentColumnIndex < this.COLUMNS - 1 && this.cursor + itemOffset < this.totalElements - 1) { - success = this.setCursor(this.cursor + 1); - } else { - success = this.setCursor(this.cursor - currentColumnIndex); - } - break; + success = this.setScrollCursor(0, this.cursor % this.COLUMNS); + } + break; + case Button.LEFT: + if (currentColumnIndex > 0) { + success = this.setCursor(this.cursor - 1); + } else if (this.scrollCursor === maxScrollCursor && currentRowIndex === onScreenRows - 1) { + success = this.setCursor(lastVisibleIndex); + } else { + success = this.setCursor(this.cursor + this.COLUMNS - 1); + } + break; + case Button.RIGHT: + if (currentColumnIndex < this.COLUMNS - 1 && this.cursor + itemOffset < this.totalElements - 1) { + success = this.setCursor(this.cursor + 1); + } else { + success = this.setCursor(this.cursor - currentColumnIndex); + } + break; } return success; } diff --git a/src/ui/settings/abstract-binding-ui-handler.ts b/src/ui/settings/abstract-binding-ui-handler.ts index 5e6dd80c6d6..9ebc3c493a4 100644 --- a/src/ui/settings/abstract-binding-ui-handler.ts +++ b/src/ui/settings/abstract-binding-ui-handler.ts @@ -1,10 +1,10 @@ import UiHandler from "../ui-handler"; import BattleScene from "../../battle-scene"; -import {Mode} from "../ui"; -import {addWindow} from "../ui-theme"; -import {addTextObject, TextStyle} from "../text"; -import {Button} from "#enums/buttons"; -import {NavigationManager} from "#app/ui/settings/navigationMenu"; +import { Mode } from "../ui"; +import { addWindow } from "../ui-theme"; +import { addTextObject, TextStyle } from "../text"; +import { Button } from "#enums/buttons"; +import { NavigationManager } from "#app/ui/settings/navigationMenu"; import i18next from "i18next"; type CancelFn = (succes?: boolean) => boolean; @@ -88,7 +88,7 @@ export default abstract class AbstractBindingUiHandler extends UiHandler { this.timerText = addTextObject(this.scene, 0, 0, "(5)", TextStyle.WINDOW); this.timerText.setOrigin(0, 0); - this.timerText.setPositionRelative(this.unlockText, (this.unlockText.width/6) + 5, 0); + this.timerText.setPositionRelative(this.unlockText, (this.unlockText.width / 6) + 5, 0); this.optionSelectContainer.add(this.timerText); this.optionSelectBg = addWindow(this.scene, (this.scene.game.canvas.width / 6) - this.getWindowWidth(), -(this.scene.game.canvas.height / 6) + this.getWindowHeight() + 28, this.getWindowWidth(), this.getWindowHeight()); @@ -170,22 +170,22 @@ export default abstract class AbstractBindingUiHandler extends UiHandler { const ui = this.getUi(); let success = false; switch (button) { - case Button.LEFT: - case Button.RIGHT: + case Button.LEFT: + case Button.RIGHT: // Toggle between action and cancel options. - const cursor = this.cursor ? 0 : 1; - success = this.setCursor(cursor); - break; - case Button.ACTION: + const cursor = this.cursor ? 0 : 1; + success = this.setCursor(cursor); + break; + case Button.ACTION: // Process actions based on current cursor position. - if (this.cursor === 0) { - this.cancelFn && this.cancelFn(); - } else { - success = this.swapAction(); - NavigationManager.getInstance().updateIcons(); - this.cancelFn && this.cancelFn(success); - } - break; + if (this.cursor === 0) { + this.cancelFn && this.cancelFn(); + } else { + success = this.swapAction(); + NavigationManager.getInstance().updateIcons(); + this.cancelFn && this.cancelFn(success); + } + break; } // Plays a select sound effect if an action was successfully processed. diff --git a/src/ui/settings/abstract-control-settings-ui-handler.ts b/src/ui/settings/abstract-control-settings-ui-handler.ts index efa262bb2e9..69f8eb241d3 100644 --- a/src/ui/settings/abstract-control-settings-ui-handler.ts +++ b/src/ui/settings/abstract-control-settings-ui-handler.ts @@ -120,7 +120,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler const actionText = addTextObject(this.scene, 0, 0, i18next.t("settings:action"), TextStyle.SETTINGS_LABEL); actionText.setOrigin(0, 0.15); - actionText.setPositionRelative(iconAction, -actionText.width/6-2, 0); + actionText.setPositionRelative(iconAction, -actionText.width / 6 - 2, 0); const iconCancel = this.scene.add.sprite(0, 0, "keyboard"); iconCancel.setOrigin(0, -0.1); @@ -129,7 +129,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler const cancelText = addTextObject(this.scene, 0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL); cancelText.setOrigin(0, 0.15); - cancelText.setPositionRelative(iconCancel, -cancelText.width/6-2, 0); + cancelText.setPositionRelative(iconCancel, -cancelText.width / 6 - 2, 0); const iconReset = this.scene.add.sprite(0, 0, "keyboard"); iconReset.setOrigin(0, -0.1); @@ -138,7 +138,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler const resetText = addTextObject(this.scene, 0, 0, i18next.t("settings:reset"), TextStyle.SETTINGS_LABEL); resetText.setOrigin(0, 0.15); - resetText.setPositionRelative(iconReset, -resetText.width/6-2, 0); + resetText.setPositionRelative(iconReset, -resetText.width / 6 - 2, 0); this.settingsContainer.add(this.optionsBg); this.settingsContainer.add(this.actionsBg); @@ -174,7 +174,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler // Fetch common setting keys such as 'Controller' and 'Gamepad Support' from gamepad settings. const commonSettingKeys = Object.keys(this.setting).slice(0, this.commonSettingsCount).map(key => this.setting[key]); // Combine common and specific bindings into a single array. - const specificBindingKeys = [...commonSettingKeys, ...Object.keys(config.settings)]; + const specificBindingKeys = [ ...commonSettingKeys, ...Object.keys(config.settings) ]; // Fetch default values for these settings and prepare to highlight selected options. const optionCursors = Object.values(Object.keys(this.settingDeviceDefaults).filter(s => specificBindingKeys.includes(s)).map(k => this.settingDeviceDefaults[k])); // Filter out settings that are not relevant to the current gamepad configuration. @@ -203,7 +203,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler const valueLabels: Phaser.GameObjects.GameObject[] = []; // Process each option for the current setting. - for (const [o, option] of this.settingDeviceOptions[this.setting[setting]].entries()) { + for (const [ o, option ] of this.settingDeviceOptions[this.setting[setting]].entries()) { // Check if the current setting is for binding keys. if (bindingSettings.includes(this.setting[setting])) { // Create a label for non-null options, typically indicating actionable options like 'change'. @@ -449,78 +449,78 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler const cursor = this.cursor + this.scrollCursor; // Calculate the absolute cursor position. const setting = this.setting[Object.keys(this.setting)[cursor]]; switch (button) { - case Button.ACTION: - if (!this.optionCursors || !this.optionValueLabels) { - return false; // TODO: is false correct as default? (previously was `undefined`) - } - if (this.settingBlacklisted.includes(setting) || !setting.includes("BUTTON_")) { - success = false; - } else { - success = this.setSetting(this.scene, setting, 1); - } - break; - case Button.UP: // Move up in the menu. - if (!this.optionValueLabels) { - return false; - } - if (cursor) { // If not at the top, move the cursor up. - if (this.cursor) { - success = this.setCursor(this.cursor - 1); - } else {// If at the top of the visible items, scroll up. - success = this.setScrollCursor(this.scrollCursor - 1); + case Button.ACTION: + if (!this.optionCursors || !this.optionValueLabels) { + return false; // TODO: is false correct as default? (previously was `undefined`) } - } else { + if (this.settingBlacklisted.includes(setting) || !setting.includes("BUTTON_")) { + success = false; + } else { + success = this.setSetting(this.scene, setting, 1); + } + break; + case Button.UP: // Move up in the menu. + if (!this.optionValueLabels) { + return false; + } + if (cursor) { // If not at the top, move the cursor up. + if (this.cursor) { + success = this.setCursor(this.cursor - 1); + } else {// If at the top of the visible items, scroll up. + success = this.setScrollCursor(this.scrollCursor - 1); + } + } else { // When at the top of the menu and pressing UP, move to the bottommost item. // First, set the cursor to the last visible element, preparing for the scroll to the end. - const successA = this.setCursor(this.rowsToDisplay - 1); - // Then, adjust the scroll to display the bottommost elements of the menu. - const successB = this.setScrollCursor(this.optionValueLabels.length - this.rowsToDisplay); - success = successA && successB; // success is just there to play the little validation sound effect - } - break; - case Button.DOWN: // Move down in the menu. - if (!this.optionValueLabels) { - return false; - } - if (cursor < this.optionValueLabels.length - 1) { - if (this.cursor < this.rowsToDisplay - 1) { - success = this.setCursor(this.cursor + 1); - } else if (this.scrollCursor < this.optionValueLabels.length - this.rowsToDisplay) { - success = this.setScrollCursor(this.scrollCursor + 1); + const successA = this.setCursor(this.rowsToDisplay - 1); + // Then, adjust the scroll to display the bottommost elements of the menu. + const successB = this.setScrollCursor(this.optionValueLabels.length - this.rowsToDisplay); + success = successA && successB; // success is just there to play the little validation sound effect } - } else { + break; + case Button.DOWN: // Move down in the menu. + if (!this.optionValueLabels) { + return false; + } + if (cursor < this.optionValueLabels.length - 1) { + if (this.cursor < this.rowsToDisplay - 1) { + success = this.setCursor(this.cursor + 1); + } else if (this.scrollCursor < this.optionValueLabels.length - this.rowsToDisplay) { + success = this.setScrollCursor(this.scrollCursor + 1); + } + } else { // When at the bottom of the menu and pressing DOWN, move to the topmost item. // First, set the cursor to the first visible element, resetting the scroll to the top. - const successA = this.setCursor(0); - // Then, reset the scroll to start from the first element of the menu. - const successB = this.setScrollCursor(0); - success = successA && successB; // Indicates a successful cursor and scroll adjustment. - } - break; - case Button.LEFT: // Move selection left within the current option set. - if (!this.optionCursors || !this.optionValueLabels) { - return false; // TODO: is false correct as default? (previously was `undefined`) - } - if (this.settingBlacklisted.includes(setting) || setting.includes("BUTTON_")) { - success = false; - } else if (this.optionCursors[cursor]) { - success = this.setOptionCursor(cursor, this.optionCursors[cursor] - 1, true); - } - break; - case Button.RIGHT: // Move selection right within the current option set. - if (!this.optionCursors || !this.optionValueLabels) { - return false; // TODO: is false correct as default? (previously was `undefined`) - } - if (this.settingBlacklisted.includes(setting) || setting.includes("BUTTON_")) { - success = false; - } else if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1) { - success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true); - } - break; - case Button.CYCLE_FORM: - case Button.CYCLE_SHINY: - success = this.navigationContainer.navigate(button); - break; + const successA = this.setCursor(0); + // Then, reset the scroll to start from the first element of the menu. + const successB = this.setScrollCursor(0); + success = successA && successB; // Indicates a successful cursor and scroll adjustment. + } + break; + case Button.LEFT: // Move selection left within the current option set. + if (!this.optionCursors || !this.optionValueLabels) { + return false; // TODO: is false correct as default? (previously was `undefined`) + } + if (this.settingBlacklisted.includes(setting) || setting.includes("BUTTON_")) { + success = false; + } else if (this.optionCursors[cursor]) { + success = this.setOptionCursor(cursor, this.optionCursors[cursor] - 1, true); + } + break; + case Button.RIGHT: // Move selection right within the current option set. + if (!this.optionCursors || !this.optionValueLabels) { + return false; // TODO: is false correct as default? (previously was `undefined`) + } + if (this.settingBlacklisted.includes(setting) || setting.includes("BUTTON_")) { + success = false; + } else if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1) { + success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true); + } + break; + case Button.CYCLE_FORM: + case Button.CYCLE_SHINY: + success = this.navigationContainer.navigate(button); + break; } } @@ -556,7 +556,7 @@ export default abstract class AbstractControlSettingsUiHandler extends UiHandler // Check if the cursor object exists, if not, create it. if (!this.cursorObj) { - const cursorWidth = (this.scene.game.canvas.width / 6) - (this.scrollBar.visible? 16 : 10); + const cursorWidth = (this.scene.game.canvas.width / 6) - (this.scrollBar.visible ? 16 : 10); this.cursorObj = this.scene.add.nineslice(0, 0, "summary_moves_cursor", undefined, cursorWidth, 16, 1, 1, 1, 1); this.cursorObj.setOrigin(0, 0); // Set the origin to the top-left corner. this.optionsContainer.add(this.cursorObj); // Add the cursor to the options container. diff --git a/src/ui/settings/abstract-settings-ui-handler.ts b/src/ui/settings/abstract-settings-ui-handler.ts index 975a32127ff..83219e1ef5a 100644 --- a/src/ui/settings/abstract-settings-ui-handler.ts +++ b/src/ui/settings/abstract-settings-ui-handler.ts @@ -77,7 +77,7 @@ export default class AbstractSettingsUiHandler extends UiHandler { const actionText = addTextObject(this.scene, 0, 0, i18next.t("settings:action"), TextStyle.SETTINGS_LABEL); actionText.setOrigin(0, 0.15); - actionText.setPositionRelative(iconAction, -actionText.width/6-2, 0); + actionText.setPositionRelative(iconAction, -actionText.width / 6 - 2, 0); const iconCancel = this.scene.add.sprite(0, 0, "keyboard"); iconCancel.setOrigin(0, -0.1); @@ -86,7 +86,7 @@ export default class AbstractSettingsUiHandler extends UiHandler { const cancelText = addTextObject(this.scene, 0, 0, i18next.t("settings:back"), TextStyle.SETTINGS_LABEL); cancelText.setOrigin(0, 0.15); - cancelText.setPositionRelative(iconCancel, -cancelText.width/6-2, 0); + cancelText.setPositionRelative(iconCancel, -cancelText.width / 6 - 2, 0); this.optionsContainer = this.scene.add.container(0, 0); @@ -224,59 +224,59 @@ export default class AbstractSettingsUiHandler extends UiHandler { } else { const cursor = this.cursor + this.scrollCursor; switch (button) { - case Button.UP: - if (cursor) { - if (this.cursor) { - success = this.setCursor(this.cursor - 1); + case Button.UP: + if (cursor) { + if (this.cursor) { + success = this.setCursor(this.cursor - 1); + } else { + success = this.setScrollCursor(this.scrollCursor - 1); + } } else { - success = this.setScrollCursor(this.scrollCursor - 1); - } - } else { // When at the top of the menu and pressing UP, move to the bottommost item. // First, set the cursor to the last visible element, preparing for the scroll to the end. - const successA = this.setCursor(this.rowsToDisplay - 1); - // Then, adjust the scroll to display the bottommost elements of the menu. - const successB = this.setScrollCursor(this.optionValueLabels.length - this.rowsToDisplay); - success = successA && successB; // success is just there to play the little validation sound effect - } - break; - case Button.DOWN: - if (cursor < this.optionValueLabels.length - 1) { - if (this.cursor < this.rowsToDisplay - 1) {// if the visual cursor is in the frame of 0 to 8 - success = this.setCursor(this.cursor + 1); - } else if (this.scrollCursor < this.optionValueLabels.length - this.rowsToDisplay) { - success = this.setScrollCursor(this.scrollCursor + 1); + const successA = this.setCursor(this.rowsToDisplay - 1); + // Then, adjust the scroll to display the bottommost elements of the menu. + const successB = this.setScrollCursor(this.optionValueLabels.length - this.rowsToDisplay); + success = successA && successB; // success is just there to play the little validation sound effect } - } else { + break; + case Button.DOWN: + if (cursor < this.optionValueLabels.length - 1) { + if (this.cursor < this.rowsToDisplay - 1) {// if the visual cursor is in the frame of 0 to 8 + success = this.setCursor(this.cursor + 1); + } else if (this.scrollCursor < this.optionValueLabels.length - this.rowsToDisplay) { + success = this.setScrollCursor(this.scrollCursor + 1); + } + } else { // When at the bottom of the menu and pressing DOWN, move to the topmost item. // First, set the cursor to the first visible element, resetting the scroll to the top. - const successA = this.setCursor(0); - // Then, reset the scroll to start from the first element of the menu. - const successB = this.setScrollCursor(0); - success = successA && successB; // Indicates a successful cursor and scroll adjustment. - } - break; - case Button.LEFT: - if (this.optionCursors[cursor]) {// Moves the option cursor left, if possible. - success = this.setOptionCursor(cursor, this.optionCursors[cursor] - 1, true); - } - break; - case Button.RIGHT: + const successA = this.setCursor(0); + // Then, reset the scroll to start from the first element of the menu. + const successB = this.setScrollCursor(0); + success = successA && successB; // Indicates a successful cursor and scroll adjustment. + } + break; + case Button.LEFT: + if (this.optionCursors[cursor]) {// Moves the option cursor left, if possible. + success = this.setOptionCursor(cursor, this.optionCursors[cursor] - 1, true); + } + break; + case Button.RIGHT: // Moves the option cursor right, if possible. - if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1) { - success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true); - } - break; - case Button.CYCLE_FORM: - case Button.CYCLE_SHINY: - success = this.navigationContainer.navigate(button); - break; - case Button.ACTION: - const setting: Setting = this.settings[cursor]; - if (setting?.activatable) { - success = this.activateSetting(setting); - } - break; + if (this.optionCursors[cursor] < this.optionValueLabels[cursor].length - 1) { + success = this.setOptionCursor(cursor, this.optionCursors[cursor] + 1, true); + } + break; + case Button.CYCLE_FORM: + case Button.CYCLE_SHINY: + success = this.navigationContainer.navigate(button); + break; + case Button.ACTION: + const setting: Setting = this.settings[cursor]; + if (setting?.activatable) { + success = this.activateSetting(setting); + } + break; } } @@ -295,9 +295,9 @@ export default class AbstractSettingsUiHandler extends UiHandler { */ activateSetting(setting: Setting): boolean { switch (setting.key) { - case SettingKeys.Move_Touch_Controls: - this.scene.inputController.moveTouchControlsHandler.enableConfigurationMode(this.getUi(), this.scene); - return true; + case SettingKeys.Move_Touch_Controls: + this.scene.inputController.moveTouchControlsHandler.enableConfigurationMode(this.getUi(), this.scene); + return true; } return false; } @@ -312,7 +312,7 @@ export default class AbstractSettingsUiHandler extends UiHandler { const ret = super.setCursor(cursor); if (!this.cursorObj) { - const cursorWidth = (this.scene.game.canvas.width / 6) - (this.scrollBar.visible? 16 : 10); + const cursorWidth = (this.scene.game.canvas.width / 6) - (this.scrollBar.visible ? 16 : 10); this.cursorObj = this.scene.add.nineslice(0, 0, "summary_moves_cursor", undefined, cursorWidth, 16, 1, 1, 1, 1); this.cursorObj.setOrigin(0, 0); this.optionsContainer.add(this.cursorObj); diff --git a/src/ui/settings/gamepad-binding-ui-handler.ts b/src/ui/settings/gamepad-binding-ui-handler.ts index 4e5b4576b85..e89529f6453 100644 --- a/src/ui/settings/gamepad-binding-ui-handler.ts +++ b/src/ui/settings/gamepad-binding-ui-handler.ts @@ -1,9 +1,9 @@ import BattleScene from "../../battle-scene"; import AbstractBindingUiHandler from "./abstract-binding-ui-handler"; -import {Mode} from "../ui"; -import {Device} from "#enums/devices"; -import {getIconWithSettingName, getKeyWithKeycode} from "#app/configs/inputs/configHandler"; -import {addTextObject, TextStyle} from "#app/ui/text"; +import { Mode } from "../ui"; +import { Device } from "#enums/devices"; +import { getIconWithSettingName, getKeyWithKeycode } from "#app/configs/inputs/configHandler"; +import { addTextObject, TextStyle } from "#app/ui/text"; export default class GamepadBindingUiHandler extends AbstractBindingUiHandler { @@ -46,7 +46,7 @@ export default class GamepadBindingUiHandler extends AbstractBindingUiHandler { } gamepadButtonDown(pad: Phaser.Input.Gamepad.Gamepad, button: Phaser.Input.Gamepad.Button, value: number): void { - const blacklist = [12, 13, 14, 15]; // d-pad buttons are blacklisted. + const blacklist = [ 12, 13, 14, 15 ]; // d-pad buttons are blacklisted. // Check conditions before processing the button press. if (!this.listening || pad.id.toLowerCase() !== this.getSelectedDevice() || blacklist.includes(button.index) || this.buttonPressed !== null) { return; diff --git a/src/ui/settings/keyboard-binding-ui-handler.ts b/src/ui/settings/keyboard-binding-ui-handler.ts index 043c5fba6a5..52b1a0e385f 100644 --- a/src/ui/settings/keyboard-binding-ui-handler.ts +++ b/src/ui/settings/keyboard-binding-ui-handler.ts @@ -1,9 +1,9 @@ import BattleScene from "../../battle-scene"; import AbstractBindingUiHandler from "./abstract-binding-ui-handler"; -import {Mode} from "../ui"; -import { getKeyWithKeycode} from "#app/configs/inputs/configHandler"; -import {Device} from "#enums/devices"; -import {addTextObject, TextStyle} from "#app/ui/text"; +import { Mode } from "../ui"; +import { getKeyWithKeycode } from "#app/configs/inputs/configHandler"; +import { Device } from "#enums/devices"; +import { addTextObject, TextStyle } from "#app/ui/text"; export default class KeyboardBindingUiHandler extends AbstractBindingUiHandler { diff --git a/src/ui/settings/move-touch-controls-handler.ts b/src/ui/settings/move-touch-controls-handler.ts index cff68fa523d..eda75a54a63 100644 --- a/src/ui/settings/move-touch-controls-handler.ts +++ b/src/ui/settings/move-touch-controls-handler.ts @@ -6,7 +6,6 @@ export const TOUCH_CONTROL_POSITIONS_LANDSCAPE = "touchControlPositionsLandscape export const TOUCH_CONTROL_POSITIONS_PORTRAIT = "touchControlPositionsPortrait"; - type ControlPosition = { id: string, x: number, y: number }; type ConfigurationEventListeners = { @@ -72,7 +71,7 @@ export default class MoveTouchControlsHandler { if (this.inConfigurationMode) { const orientation = document.querySelector("#touchControls #orientation"); if (orientation) { - orientation.textContent = this.isLandscapeMode? "Landscape" : "Portrait"; + orientation.textContent = this.isLandscapeMode ? "Landscape" : "Portrait"; } } const positions = this.getSavedPositionsOfCurrentOrientation() ?? []; @@ -288,7 +287,7 @@ export default class MoveTouchControlsHandler { * @returns All control groups of the touch controls. */ private getControlGroupElements(): HTMLDivElement[] { - return [...document.querySelectorAll("#touchControls .control-group")] as HTMLDivElement[]; + return [ ...document.querySelectorAll("#touchControls .control-group") ] as HTMLDivElement[]; } /** diff --git a/src/ui/settings/navigationMenu.ts b/src/ui/settings/navigationMenu.ts index 7d7761b7b69..ab86fa1569a 100644 --- a/src/ui/settings/navigationMenu.ts +++ b/src/ui/settings/navigationMenu.ts @@ -1,9 +1,9 @@ import BattleScene from "#app/battle-scene"; -import {Mode} from "#app/ui/ui"; -import {InputsIcons} from "#app/ui/settings/abstract-control-settings-ui-handler"; -import {addTextObject, setTextStyle, TextStyle} from "#app/ui/text"; -import {addWindow} from "#app/ui/ui-theme"; -import {Button} from "#enums/buttons"; +import { Mode } from "#app/ui/ui"; +import { InputsIcons } from "#app/ui/settings/abstract-control-settings-ui-handler"; +import { addTextObject, setTextStyle, TextStyle } from "#app/ui/text"; +import { addWindow } from "#app/ui/ui-theme"; +import { Button } from "#enums/buttons"; import i18next from "i18next"; const LEFT = "LEFT"; @@ -33,7 +33,7 @@ export class NavigationManager { Mode.SETTINGS_GAMEPAD, Mode.SETTINGS_KEYBOARD, ]; - this.labels = [i18next.t("settings:general"), i18next.t("settings:display"), i18next.t("settings:audio"), i18next.t("settings:gamepad"), i18next.t("settings:keyboard")]; + this.labels = [ i18next.t("settings:general"), i18next.t("settings:display"), i18next.t("settings:audio"), i18next.t("settings:gamepad"), i18next.t("settings:keyboard") ]; } public reset() { @@ -134,11 +134,11 @@ export default class NavigationMenu extends Phaser.GameObjects.Container { this.navigationIcons["BUTTON_CYCLE_SHINY"] = iconNextTab; let relative: Phaser.GameObjects.Sprite | Phaser.GameObjects.Text = iconPreviousTab; - let relativeWidth: number = iconPreviousTab.width*6; + let relativeWidth: number = iconPreviousTab.width * 6; for (const label of navigationManager.labels) { const labelText = addTextObject(this.scene, 0, 0, label, TextStyle.SETTINGS_LABEL); labelText.setOrigin(0, 0); - labelText.setPositionRelative(relative, 6 + relativeWidth/6, 0); + labelText.setPositionRelative(relative, 6 + relativeWidth / 6, 0); this.add(labelText); this.headerTitles.push(labelText); relative = labelText; @@ -158,7 +158,7 @@ export default class NavigationMenu extends Phaser.GameObjects.Container { const navigationManager = NavigationManager.getInstance(); const posSelected = navigationManager.modes.indexOf(navigationManager.selectedMode); - for (const [index, title] of this.headerTitles.entries()) { + for (const [ index, title ] of this.headerTitles.entries()) { setTextStyle(title, this.scene, index === posSelected ? TextStyle.SETTINGS_SELECTED : TextStyle.SETTINGS_LABEL); } } @@ -198,12 +198,12 @@ export default class NavigationMenu extends Phaser.GameObjects.Container { navigate(button: Button): boolean { const navigationManager = NavigationManager.getInstance(); switch (button) { - case Button.CYCLE_FORM: - navigationManager.navigate(this.scene, LEFT); - return true; - case Button.CYCLE_SHINY: - navigationManager.navigate(this.scene, RIGHT); - return true; + case Button.CYCLE_FORM: + navigationManager.navigate(this.scene, LEFT); + return true; + case Button.CYCLE_SHINY: + navigationManager.navigate(this.scene, RIGHT); + return true; } return false; } diff --git a/src/ui/settings/settings-display-ui-handler.ts b/src/ui/settings/settings-display-ui-handler.ts index 3d602c50a78..a25dbf87b7d 100644 --- a/src/ui/settings/settings-display-ui-handler.ts +++ b/src/ui/settings/settings-display-ui-handler.ts @@ -23,79 +23,79 @@ export default class SettingsDisplayUiHandler extends AbstractSettingsUiHandler if (languageIndex >= 0) { const currentLocale = localStorage.getItem("prLang"); switch (currentLocale) { - case "en": - this.settings[languageIndex].options[0] = { - value: "English", - label: "English", - }; - break; - case "es": - this.settings[languageIndex].options[0] = { - value: "Español", - label: "Español", - }; - break; - case "it": - this.settings[languageIndex].options[0] = { - value: "Italiano", - label: "Italiano", - }; - break; - case "fr": - this.settings[languageIndex].options[0] = { - value: "Français", - label: "Français", - }; - break; - case "de": - this.settings[languageIndex].options[0] = { - value: "Deutsch", - label: "Deutsch", - }; - break; - case "pt-BR": - this.settings[languageIndex].options[0] = { - value: "Português (BR)", - label: "Português (BR)", - }; - break; - case "zh-CN": - this.settings[languageIndex].options[0] = { - value: "简体中文", - label: "简体中文", - }; - break; - case "zh-TW": - this.settings[languageIndex].options[0] = { - value: "繁體中文", - label: "繁體中文", - }; - break; - case "ko": - case "ko-KR": - this.settings[languageIndex].options[0] = { - value: "한국어", - label: "한국어", - }; - break; - case "ja": - this.settings[languageIndex].options[0] = { - value: "日本語", - label: "日本語", - }; - break; - case "ca-ES": - this.settings[languageIndex].options[0] = { - value: "Català", - label: "Català", - }; - break; - default: - this.settings[languageIndex].options[0] = { - value: "English", - label: "English", - }; - break; + case "en": + this.settings[languageIndex].options[0] = { + value: "English", + label: "English", + }; + break; + case "es": + this.settings[languageIndex].options[0] = { + value: "Español", + label: "Español", + }; + break; + case "it": + this.settings[languageIndex].options[0] = { + value: "Italiano", + label: "Italiano", + }; + break; + case "fr": + this.settings[languageIndex].options[0] = { + value: "Français", + label: "Français", + }; + break; + case "de": + this.settings[languageIndex].options[0] = { + value: "Deutsch", + label: "Deutsch", + }; + break; + case "pt-BR": + this.settings[languageIndex].options[0] = { + value: "Português (BR)", + label: "Português (BR)", + }; + break; + case "zh-CN": + this.settings[languageIndex].options[0] = { + value: "简体中文", + label: "简体中文", + }; + break; + case "zh-TW": + this.settings[languageIndex].options[0] = { + value: "繁體中文", + label: "繁體中文", + }; + break; + case "ko": + case "ko-KR": + this.settings[languageIndex].options[0] = { + value: "한국어", + label: "한국어", + }; + break; + case "ja": + this.settings[languageIndex].options[0] = { + value: "日本語", + label: "日本語", + }; + break; + case "ca-ES": + this.settings[languageIndex].options[0] = { + value: "Català", + label: "Català", + }; + break; + default: + this.settings[languageIndex].options[0] = { + value: "English", + label: "English", + }; + break; } } diff --git a/src/ui/settings/settings-gamepad-ui-handler.ts b/src/ui/settings/settings-gamepad-ui-handler.ts index 63a9d2ab23b..864142e055b 100644 --- a/src/ui/settings/settings-gamepad-ui-handler.ts +++ b/src/ui/settings/settings-gamepad-ui-handler.ts @@ -1,6 +1,6 @@ import BattleScene from "../../battle-scene"; -import {addTextObject, TextStyle} from "../text"; -import {Mode} from "../ui"; +import { addTextObject, TextStyle } from "../text"; +import { Mode } from "../ui"; import { setSettingGamepad, SettingGamepad, @@ -11,10 +11,10 @@ import { import pad_xbox360 from "#app/configs/inputs/pad_xbox360"; import pad_dualshock from "#app/configs/inputs/pad_dualshock"; import pad_unlicensedSNES from "#app/configs/inputs/pad_unlicensedSNES"; -import {InterfaceConfig} from "#app/inputs-controller"; +import { InterfaceConfig } from "#app/inputs-controller"; import AbstractControlSettingsUiHandler from "#app/ui/settings/abstract-control-settings-ui-handler"; -import {Device} from "#enums/devices"; -import {truncateString} from "#app/utils"; +import { Device } from "#enums/devices"; +import { truncateString } from "#app/utils"; import i18next from "i18next"; /** @@ -37,7 +37,7 @@ export default class SettingsGamepadUiHandler extends AbstractControlSettingsUiH this.setting = SettingGamepad; this.settingDeviceDefaults = settingGamepadDefaults; this.settingDeviceOptions = settingGamepadOptions; - this.configs = [pad_xbox360, pad_dualshock, pad_unlicensedSNES]; + this.configs = [ pad_xbox360, pad_dualshock, pad_unlicensedSNES ]; this.commonSettingsCount = 2; this.localStoragePropertyName = "settingsGamepad"; this.settingBlacklisted = settingGamepadBlackList; @@ -94,7 +94,7 @@ export default class SettingsGamepadUiHandler extends AbstractControlSettingsUiH this.resetScroll(); // Iterate over the keys in the settingDevice enumeration. - for (const [index, key] of Object.keys(this.setting).entries()) { + for (const [ index, key ] of Object.keys(this.setting).entries()) { const setting = this.setting[key]; // Get the actual setting value using the key. // Check if the current setting corresponds to the controller setting. diff --git a/src/ui/settings/settings-keyboard-ui-handler.ts b/src/ui/settings/settings-keyboard-ui-handler.ts index 7e020034bc6..17d91b27c57 100644 --- a/src/ui/settings/settings-keyboard-ui-handler.ts +++ b/src/ui/settings/settings-keyboard-ui-handler.ts @@ -1,5 +1,5 @@ import BattleScene from "../../battle-scene"; -import {Mode} from "../ui"; +import { Mode } from "../ui"; import cfg_keyboard_qwerty from "#app/configs/inputs/cfg_keyboard_qwerty"; import { setSettingKeyboard, @@ -8,13 +8,13 @@ import { settingKeyboardDefaults, settingKeyboardOptions } from "#app/system/settings/settings-keyboard"; -import {reverseValueToKeySetting, truncateString} from "#app/utils"; +import { reverseValueToKeySetting, truncateString } from "#app/utils"; import AbstractControlSettingsUiHandler from "#app/ui/settings/abstract-control-settings-ui-handler"; -import {InterfaceConfig} from "#app/inputs-controller"; -import {addTextObject, TextStyle} from "#app/ui/text"; -import {deleteBind} from "#app/configs/inputs/configHandler"; -import {Device} from "#enums/devices"; -import {NavigationManager} from "#app/ui/settings/navigationMenu"; +import { InterfaceConfig } from "#app/inputs-controller"; +import { addTextObject, TextStyle } from "#app/ui/text"; +import { deleteBind } from "#app/configs/inputs/configHandler"; +import { Device } from "#enums/devices"; +import { NavigationManager } from "#app/ui/settings/navigationMenu"; import i18next from "i18next"; /** @@ -35,7 +35,7 @@ export default class SettingsKeyboardUiHandler extends AbstractControlSettingsUi this.setting = SettingKeyboard; this.settingDeviceDefaults = settingKeyboardDefaults; this.settingDeviceOptions = settingKeyboardOptions; - this.configs = [cfg_keyboard_qwerty]; + this.configs = [ cfg_keyboard_qwerty ]; this.commonSettingsCount = 0; this.textureOverride = "keyboard"; this.localStoragePropertyName = "settingsKeyboard"; @@ -71,13 +71,12 @@ export default class SettingsKeyboardUiHandler extends AbstractControlSettingsUi const deleteText = addTextObject(this.scene, 0, 0, i18next.t("settings:delete"), TextStyle.SETTINGS_LABEL); deleteText.setOrigin(0, 0.15); - deleteText.setPositionRelative(iconDelete, -deleteText.width/6-2, 0); + deleteText.setPositionRelative(iconDelete, -deleteText.width / 6 - 2, 0); this.settingsContainer.add(iconDelete); this.settingsContainer.add(deleteText); - // Map the 'noKeyboard' layout options for easy access. this.layout["noKeyboard"].optionsContainer = optionsContainer; this.layout["noKeyboard"].label = label; @@ -87,7 +86,7 @@ export default class SettingsKeyboardUiHandler extends AbstractControlSettingsUi * Handle the home key press event. */ onHomeDown(): void { - if (![Mode.SETTINGS_KEYBOARD, Mode.SETTINGS_GAMEPAD].includes(this.scene.ui.getMode())) { + if (![ Mode.SETTINGS_KEYBOARD, Mode.SETTINGS_GAMEPAD ].includes(this.scene.ui.getMode())) { return; } this.scene.gameData.resetMappingToFactory(); @@ -142,7 +141,7 @@ export default class SettingsKeyboardUiHandler extends AbstractControlSettingsUi this.updateBindings(); // Iterate over the keys in the settingDevice enumeration. - for (const [index, key] of Object.keys(this.setting).entries()) { + for (const [ index, key ] of Object.keys(this.setting).entries()) { const setting = this.setting[key]; // Get the actual setting value using the key. // Check if the current setting corresponds to the layout setting. diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 38445f79e05..bb999dc736a 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -46,6 +46,7 @@ import { StarterContainer } from "#app/ui/starter-container"; import { DropDownColumn, FilterBar } from "#app/ui/filter-bar"; import { ScrollBar } from "#app/ui/scroll-bar"; import { SelectChallengePhase } from "#app/phases/select-challenge-phase"; +import { EncounterPhase } from "#app/phases/encounter-phase"; import { TitlePhase } from "#app/phases/title-phase"; import { Abilities } from "#enums/abilities"; import { getPassiveCandyCount, getValueReductionCandyCounts, getSameSpeciesEggCandyCounts } from "#app/data/balance/starters"; @@ -143,7 +144,7 @@ function calcStarterPosition(index: number, scrollCursor:number = 0): {x: number const x = (index % 9) * 18; const y = yOffset + (Math.floor(index / 9) - scrollCursor) * height; - return {x: x, y: y}; + return { x: x, y: y }; } /** @@ -186,7 +187,7 @@ function findClosestStarterRow(index: number, numberOfRows: number) { const currentY = calcStarterIconY(index) - 13; let smallestDistance = teamWindowHeight; let closestRowIndex = 0; - for (let i=0; i < numberOfRows; i++) { + for (let i = 0; i < numberOfRows; i++) { const distance = Math.abs(currentY - calcStarterPosition(i * 9).y); if (distance < smallestDistance) { closestRowIndex = i; @@ -308,13 +309,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { private starterIconsCursorObj: Phaser.GameObjects.Image; private valueLimitLabel: Phaser.GameObjects.Text; private startCursorObj: Phaser.GameObjects.NineSlice; - // private starterValueLabels: Phaser.GameObjects.Text[]; - // private shinyIcons: Phaser.GameObjects.Image[][]; - // private hiddenAbilityIcons: Phaser.GameObjects.Image[]; - // private classicWinIcons: Phaser.GameObjects.Image[]; - // private candyUpgradeIcon: Phaser.GameObjects.Image[]; - // private candyUpgradeOverlayIcon: Phaser.GameObjects.Image[]; - // + private iconAnimHandler: PokemonIconAnimHandler; //variables to keep track of the dynamically rendered list of instruction prompts for starter select @@ -358,7 +353,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.starterSelectContainer.add(this.shinyOverlay); const starterContainerWindow = addWindow(this.scene, speciesContainerX, filterBarHeight + 1, 175, 161); - const starterContainerBg = this.scene.add.image(speciesContainerX+1, filterBarHeight + 2, "starter_container_bg"); + const starterContainerBg = this.scene.add.image(speciesContainerX + 1, filterBarHeight + 2, "starter_container_bg"); starterContainerBg.setOrigin(0, 0); this.starterSelectContainer.add(starterContainerBg); @@ -588,15 +583,15 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonEggMoveBgs = []; this.pokemonEggMoveLabels = []; - this.valueLimitLabel = addTextObject(this.scene, teamWindowX+17, 150, "0/10", TextStyle.TOOLTIP_CONTENT); + this.valueLimitLabel = addTextObject(this.scene, teamWindowX + 17, 150, "0/10", TextStyle.TOOLTIP_CONTENT); this.valueLimitLabel.setOrigin(0.5, 0); this.starterSelectContainer.add(this.valueLimitLabel); - const startLabel = addTextObject(this.scene, teamWindowX+17, 162, i18next.t("common:start"), TextStyle.TOOLTIP_CONTENT); + const startLabel = addTextObject(this.scene, teamWindowX + 17, 162, i18next.t("common:start"), TextStyle.TOOLTIP_CONTENT); startLabel.setOrigin(0.5, 0); this.starterSelectContainer.add(startLabel); - this.startCursorObj = this.scene.add.nineslice(teamWindowX+4, 160, "select_cursor", undefined, 26, 15, 6, 6, 6, 6); + this.startCursorObj = this.scene.add.nineslice(teamWindowX + 4, 160, "select_cursor", undefined, 26, 15, 6, 6, 6, 6); this.startCursorObj.setVisible(false); this.startCursorObj.setOrigin(0, 0); this.starterSelectContainer.add(this.startCursorObj); @@ -1155,7 +1150,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { ease: "Cubic.easeOut", yoyo: true } - ],}; + ], }; const isPassiveAvailable = this.isPassiveAvailable(species.speciesId); const isValueReductionAvailable = this.isValueReductionAvailable(species.speciesId); @@ -1308,109 +1303,119 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } else if (this.startCursorObj.visible) { // this checks to see if the start button is selected switch (button) { - case Button.ACTION: - if (this.tryStart(true)) { + case Button.ACTION: + if (this.tryStart(true)) { + success = true; + } else { + error = true; + } + break; + case Button.UP: + // UP from start button: go to pokemon in team if any, otherwise filter + this.startCursorObj.setVisible(false); + if (this.starterSpecies.length > 0) { + this.starterIconsCursorIndex = this.starterSpecies.length - 1; + this.moveStarterIconsCursor(this.starterIconsCursorIndex); + } else { + this.startCursorObj.setVisible(false); + this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1); + this.setFilterMode(true); + } success = true; - } else { - error = true; - } - break; - case Button.UP: - this.startCursorObj.setVisible(false); - if (this.starterSpecies.length > 0) { - this.starterIconsCursorIndex = this.starterSpecies.length - 1; - this.moveStarterIconsCursor(this.starterIconsCursorIndex); - } else { - // up from start button with no Pokemon in the team > go to filter + break; + case Button.DOWN: + // DOWN from start button: Go to filters this.startCursorObj.setVisible(false); this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1); this.setFilterMode(true); - } - success = true; - break; - case Button.DOWN: - this.startCursorObj.setVisible(false); - if (this.starterSpecies.length > 0) { - this.starterIconsCursorIndex = 0; - this.moveStarterIconsCursor(this.starterIconsCursorIndex); - } else { - // down from start button with no Pokemon in the team > go to filter - this.startCursorObj.setVisible(false); - this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1); - this.setFilterMode(true); - } - success = true; - break; - case Button.LEFT: - this.startCursorObj.setVisible(false); - this.cursorObj.setVisible(true); - success = this.setCursor(onScreenFirstIndex + (onScreenNumberOfRows-1) * 9 + 8); // set last column - success = true; - break; - case Button.RIGHT: - this.startCursorObj.setVisible(false); - this.cursorObj.setVisible(true); - success = this.setCursor(onScreenFirstIndex + (onScreenNumberOfRows-1) * 9); // set first column - success = true; - break; + success = true; + break; + case Button.LEFT: + if (numberOfStarters > 0) { + this.startCursorObj.setVisible(false); + this.cursorObj.setVisible(true); + this.setCursor(onScreenFirstIndex + (onScreenNumberOfRows - 1) * 9 + 8); // set last column + success = true; + } + break; + case Button.RIGHT: + if (numberOfStarters > 0) { + this.startCursorObj.setVisible(false); + this.cursorObj.setVisible(true); + this.setCursor(onScreenFirstIndex + (onScreenNumberOfRows - 1) * 9); // set first column + success = true; + } + break; } } else if (this.filterMode) { switch (button) { - case Button.LEFT: - if (this.filterBarCursor > 0) { - success = this.setCursor(this.filterBarCursor - 1); - } else { - success = this.setCursor(this.filterBar.numFilters - 1); - } - break; - case Button.RIGHT: - if (this.filterBarCursor < this.filterBar.numFilters - 1) { - success = this.setCursor(this.filterBarCursor + 1); - } else { - success = this.setCursor(0); - } - break; - case Button.UP: - if (this.filterBar.openDropDown) { - success = this.filterBar.decDropDownCursor(); - // else if there is filtered starters - } else if (numberOfStarters > 0) { - // UP from filter bar to bottom of Pokemon list - this.setFilterMode(false); - this.scrollCursor = Math.max(0, numOfRows - 9); - this.updateScroll(); - const proportion = (this.filterBarCursor + 0.5) / this.filterBar.numFilters; - const targetCol = Math.min(8, Math.floor(proportion * 11)); - if (numberOfStarters % 9 > targetCol) { - this.setCursor(numberOfStarters - (numberOfStarters) % 9 + targetCol); + case Button.LEFT: + if (this.filterBarCursor > 0) { + success = this.setCursor(this.filterBarCursor - 1); } else { - this.setCursor(Math.max(numberOfStarters - (numberOfStarters) % 9 + targetCol - 9, 0)); + success = this.setCursor(this.filterBar.numFilters - 1); + } + break; + case Button.RIGHT: + if (this.filterBarCursor < this.filterBar.numFilters - 1) { + success = this.setCursor(this.filterBarCursor + 1); + } else { + success = this.setCursor(0); + } + break; + case Button.UP: + if (this.filterBar.openDropDown) { + success = this.filterBar.decDropDownCursor(); + } else if (this.filterBarCursor === this.filterBar.numFilters - 1 && this.starterSpecies.length > 0) { + // UP from the last filter, move to start button + this.setFilterMode(false); + this.cursorObj.setVisible(false); + this.startCursorObj.setVisible(true); + success = true; + } else if (numberOfStarters > 0) { + // UP from filter bar to bottom of Pokemon list + this.setFilterMode(false); + this.scrollCursor = Math.max(0, numOfRows - 9); + this.updateScroll(); + const proportion = (this.filterBarCursor + 0.5) / this.filterBar.numFilters; + const targetCol = Math.min(8, Math.floor(proportion * 11)); + if (numberOfStarters % 9 > targetCol) { + this.setCursor(numberOfStarters - (numberOfStarters) % 9 + targetCol); + } else { + this.setCursor(Math.max(numberOfStarters - (numberOfStarters) % 9 + targetCol - 9, 0)); + } + success = true; + } + break; + case Button.DOWN: + if (this.filterBar.openDropDown) { + success = this.filterBar.incDropDownCursor(); + } else if (this.filterBarCursor === this.filterBar.numFilters - 1 && this.starterSpecies.length > 0) { + // DOWN from the last filter, move to Pokemon in party if any + this.setFilterMode(false); + this.cursorObj.setVisible(false); + this.starterIconsCursorIndex = 0; + this.moveStarterIconsCursor(this.starterIconsCursorIndex); + success = true; + } else if (numberOfStarters > 0) { + // DOWN from filter bar to top of Pokemon list + this.setFilterMode(false); + this.scrollCursor = 0; + this.updateScroll(); + const proportion = this.filterBarCursor / Math.max(1, this.filterBar.numFilters - 1); + const targetCol = Math.min(8, Math.floor(proportion * 11)); + this.setCursor(Math.min(targetCol, numberOfStarters)); + success = true; + } + break; + case Button.ACTION: + if (!this.filterBar.openDropDown) { + this.filterBar.toggleDropDown(this.filterBarCursor); + } else { + this.filterBar.toggleOptionState(); } success = true; - } - break; - case Button.DOWN: - if (this.filterBar.openDropDown) { - success = this.filterBar.incDropDownCursor(); - } else if (numberOfStarters > 0) { - // DOWN from filter bar to top of Pokemon list - this.setFilterMode(false); - this.scrollCursor = 0; - this.updateScroll(); - const proportion = this.filterBarCursor / Math.max(1, this.filterBar.numFilters - 1); - const targetCol = Math.min(8, Math.floor(proportion * 11)); - this.setCursor(Math.min(targetCol, numberOfStarters)); - success = true; - } - break; - case Button.ACTION: - if (!this.filterBar.openDropDown) { - this.filterBar.toggleDropDown(this.filterBarCursor); - } else { - this.filterBar.toggleOptionState(); - } - success = true; - break; + break; } } else { @@ -1434,7 +1439,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const ui = this.getUi(); let options: any[] = []; // TODO: add proper type - const [isDupe, removeIndex]: [boolean, number] = this.isInParty(this.lastSpecies); // checks to see if the pokemon is a duplicate; if it is, returns the index that will be removed + const [ isDupe, removeIndex ]: [boolean, number] = this.isInParty(this.lastSpecies); // checks to see if the pokemon is a duplicate; if it is, returns the index that will be removed const isPartyValid = this.isPartyValid(); const isValidForChallenge = new Utils.BooleanHolder(true); @@ -1784,13 +1789,14 @@ export default class StarterSelectUiHandler extends MessageUiHandler { options.push({ label: `x${sameSpeciesEggCost} ${i18next.t("starterSelectUiHandler:sameSpeciesEgg")}`, handler: () => { - if (this.scene.gameData.eggs.length < 99 && (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= sameSpeciesEggCost)) { + if ((this.scene.gameData.eggs.length < 99 || Overrides.UNLIMITED_EGG_COUNT_OVERRIDE) + && (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= sameSpeciesEggCost)) { if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) { starterData.candyCount -= sameSpeciesEggCost; } this.pokemonCandyCountText.setText(`x${starterData.candyCount}`); - const egg = new Egg({scene: this.scene, species: this.lastSpecies.speciesId, sourceType: EggSourceType.SAME_SPECIES_EGG}); + const egg = new Egg({ scene: this.scene, species: this.lastSpecies.speciesId, sourceType: EggSourceType.SAME_SPECIES_EGG }); egg.addEggToGameData(this.scene); this.scene.gameData.saveSystem().then(success => { @@ -1850,259 +1856,259 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } else { const props = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId)); switch (button) { - case Button.CYCLE_SHINY: - if (this.canCycleShiny) { - starterAttributes.shiny = starterAttributes.shiny !== undefined ? !starterAttributes.shiny : false; + case Button.CYCLE_SHINY: + if (this.canCycleShiny) { + starterAttributes.shiny = starterAttributes.shiny !== undefined ? !starterAttributes.shiny : false; - if (starterAttributes.shiny) { + if (starterAttributes.shiny) { // Change to shiny, we need to get the proper default variant - const newProps = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId)); - const newVariant = starterAttributes.variant ? starterAttributes.variant as Variant : newProps.variant; - this.setSpeciesDetails(this.lastSpecies, true, undefined, undefined, newVariant, undefined, undefined); + const newProps = this.scene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId)); + const newVariant = starterAttributes.variant ? starterAttributes.variant as Variant : newProps.variant; + this.setSpeciesDetails(this.lastSpecies, true, undefined, undefined, newVariant, undefined, undefined); - this.scene.playSound("se/sparkle"); - // Set the variant label to the shiny tint - const tint = getVariantTint(newVariant); - this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant)); - this.pokemonShinyIcon.setTint(tint); - this.pokemonShinyIcon.setVisible(true); - } else { - this.setSpeciesDetails(this.lastSpecies, false, undefined, undefined, 0, undefined, undefined); - this.pokemonShinyIcon.setVisible(false); - success = true; - } - } - break; - case Button.CYCLE_FORM: - if (this.canCycleForm) { - const formCount = this.lastSpecies.forms.length; - let newFormIndex = props.formIndex; - do { - newFormIndex = (newFormIndex + 1) % formCount; - if (this.lastSpecies.forms[newFormIndex].isStarterSelectable && this.speciesStarterDexEntry!.caughtAttr! & this.scene.gameData.getFormAttr(newFormIndex)) { // TODO: are those bangs correct? - break; + this.scene.playSound("se/sparkle"); + // Set the variant label to the shiny tint + const tint = getVariantTint(newVariant); + this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant)); + this.pokemonShinyIcon.setTint(tint); + this.pokemonShinyIcon.setVisible(true); + } else { + this.setSpeciesDetails(this.lastSpecies, false, undefined, undefined, 0, undefined, undefined); + this.pokemonShinyIcon.setVisible(false); + success = true; } - } while (newFormIndex !== props.formIndex); - starterAttributes.form = newFormIndex; // store the selected form - this.setSpeciesDetails(this.lastSpecies, undefined, newFormIndex, undefined, undefined, undefined, undefined); - success = true; - } - break; - case Button.CYCLE_GENDER: - if (this.canCycleGender) { - starterAttributes.female = !props.female; - this.setSpeciesDetails(this.lastSpecies, undefined, undefined, !props.female, undefined, undefined, undefined); - success = true; - } - break; - case Button.CYCLE_ABILITY: - if (this.canCycleAbility) { - const abilityCount = this.lastSpecies.getAbilityCount(); - const abilityAttr = this.scene.gameData.starterData[this.lastSpecies.speciesId].abilityAttr; - const hasAbility1 = abilityAttr & AbilityAttr.ABILITY_1; - let newAbilityIndex = this.abilityCursor; - do { - newAbilityIndex = (newAbilityIndex + 1) % abilityCount; - if (newAbilityIndex === 0) { - if (hasAbility1) { + } + break; + case Button.CYCLE_FORM: + if (this.canCycleForm) { + const formCount = this.lastSpecies.forms.length; + let newFormIndex = props.formIndex; + do { + newFormIndex = (newFormIndex + 1) % formCount; + if (this.lastSpecies.forms[newFormIndex].isStarterSelectable && this.speciesStarterDexEntry!.caughtAttr! & this.scene.gameData.getFormAttr(newFormIndex)) { // TODO: are those bangs correct? break; } - } else if (newAbilityIndex === 1) { + } while (newFormIndex !== props.formIndex); + starterAttributes.form = newFormIndex; // store the selected form + this.setSpeciesDetails(this.lastSpecies, undefined, newFormIndex, undefined, undefined, undefined, undefined); + success = true; + } + break; + case Button.CYCLE_GENDER: + if (this.canCycleGender) { + starterAttributes.female = !props.female; + this.setSpeciesDetails(this.lastSpecies, undefined, undefined, !props.female, undefined, undefined, undefined); + success = true; + } + break; + case Button.CYCLE_ABILITY: + if (this.canCycleAbility) { + const abilityCount = this.lastSpecies.getAbilityCount(); + const abilityAttr = this.scene.gameData.starterData[this.lastSpecies.speciesId].abilityAttr; + const hasAbility1 = abilityAttr & AbilityAttr.ABILITY_1; + let newAbilityIndex = this.abilityCursor; + do { + newAbilityIndex = (newAbilityIndex + 1) % abilityCount; + if (newAbilityIndex === 0) { + if (hasAbility1) { + break; + } + } else if (newAbilityIndex === 1) { // If ability 1 and 2 are the same and ability 1 is unlocked, skip over ability 2 - if (this.lastSpecies.ability1 === this.lastSpecies.ability2 && hasAbility1) { - newAbilityIndex = (newAbilityIndex + 1) % abilityCount; - } - break; - } else { - if (abilityAttr & AbilityAttr.ABILITY_HIDDEN) { + if (this.lastSpecies.ability1 === this.lastSpecies.ability2 && hasAbility1) { + newAbilityIndex = (newAbilityIndex + 1) % abilityCount; + } break; + } else { + if (abilityAttr & AbilityAttr.ABILITY_HIDDEN) { + break; + } } - } - } while (newAbilityIndex !== this.abilityCursor); - starterAttributes.ability = newAbilityIndex; // store the selected ability + } while (newAbilityIndex !== this.abilityCursor); + starterAttributes.ability = newAbilityIndex; // store the selected ability - const { visible: tooltipVisible } = this.scene.ui.getTooltip(); + const { visible: tooltipVisible } = this.scene.ui.getTooltip(); - if (tooltipVisible && this.activeTooltip === "ABILITY") { - const newAbility = allAbilities[this.lastSpecies.getAbility(newAbilityIndex)]; - this.scene.ui.editTooltip(`${newAbility.name}`, `${newAbility.description}`); - } + if (tooltipVisible && this.activeTooltip === "ABILITY") { + const newAbility = allAbilities[this.lastSpecies.getAbility(newAbilityIndex)]; + this.scene.ui.editTooltip(`${newAbility.name}`, `${newAbility.description}`); + } - this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, newAbilityIndex, undefined); - success = true; - } - break; - case Button.CYCLE_NATURE: - if (this.canCycleNature) { - const natures = this.scene.gameData.getNaturesForAttr(this.speciesStarterDexEntry?.natureAttr); - const natureIndex = natures.indexOf(this.natureCursor); - const newNature = natures[natureIndex < natures.length - 1 ? natureIndex + 1 : 0]; - // store cycled nature as default - starterAttributes.nature = newNature as unknown as integer; - this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, newNature, undefined); - success = true; - } - break; - case Button.V: - if (this.canCycleVariant) { - let newVariant = props.variant; - do { - newVariant = (newVariant + 1) % 3; - if (!newVariant) { - if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.DEFAULT_VARIANT) { // TODO: is this bang correct? - break; - } - } else if (newVariant === 1) { - if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_2) { // TODO: is this bang correct? - break; - } - } else { - if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_3) { // TODO: is this bang correct? - break; - } - } - } while (newVariant !== props.variant); - starterAttributes.variant = newVariant; // store the selected variant - this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newVariant as Variant, undefined, undefined); - // Cycle tint based on current sprite tint - const tint = getVariantTint(newVariant as Variant); - this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant as Variant)); - this.pokemonShinyIcon.setTint(tint); - success = true; - } - break; - case Button.UP: - if (!this.starterIconsCursorObj.visible) { - if (currentRow > 0) { - if (this.scrollCursor > 0 && currentRow - this.scrollCursor === 0) { - this.scrollCursor--; - this.updateScroll(); - } - success = this.setCursor(this.cursor - 9); - } else { - this.filterBarCursor = this.filterBar.getNearestFilter(this.filteredStarterContainers[this.cursor]); - this.setFilterMode(true); + this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, newAbilityIndex, undefined); success = true; } - } else { - if (this.starterIconsCursorIndex === 0) { + break; + case Button.CYCLE_NATURE: + if (this.canCycleNature) { + const natures = this.scene.gameData.getNaturesForAttr(this.speciesStarterDexEntry?.natureAttr); + const natureIndex = natures.indexOf(this.natureCursor); + const newNature = natures[natureIndex < natures.length - 1 ? natureIndex + 1 : 0]; + // store cycled nature as default + starterAttributes.nature = newNature as unknown as integer; + this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, undefined, undefined, newNature, undefined); + success = true; + } + break; + case Button.V: + if (this.canCycleVariant) { + let newVariant = props.variant; + do { + newVariant = (newVariant + 1) % 3; + if (!newVariant) { + if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.DEFAULT_VARIANT) { // TODO: is this bang correct? + break; + } + } else if (newVariant === 1) { + if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_2) { // TODO: is this bang correct? + break; + } + } else { + if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.VARIANT_3) { // TODO: is this bang correct? + break; + } + } + } while (newVariant !== props.variant); + starterAttributes.variant = newVariant; // store the selected variant + this.setSpeciesDetails(this.lastSpecies, undefined, undefined, undefined, newVariant as Variant, undefined, undefined); + // Cycle tint based on current sprite tint + const tint = getVariantTint(newVariant as Variant); + this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant as Variant)); + this.pokemonShinyIcon.setTint(tint); + success = true; + } + break; + case Button.UP: + if (!this.starterIconsCursorObj.visible) { + if (currentRow > 0) { + if (this.scrollCursor > 0 && currentRow - this.scrollCursor === 0) { + this.scrollCursor--; + this.updateScroll(); + } + success = this.setCursor(this.cursor - 9); + } else { + this.filterBarCursor = this.filterBar.getNearestFilter(this.filteredStarterContainers[this.cursor]); + this.setFilterMode(true); + success = true; + } + } else { + if (this.starterIconsCursorIndex === 0) { // Up from first Pokemon in the team > go to filter - this.starterIconsCursorObj.setVisible(false); - this.setSpecies(null); - this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1); - this.setFilterMode(true); - } else { - this.starterIconsCursorIndex--; - this.moveStarterIconsCursor(this.starterIconsCursorIndex); - } - success = true; - } - break; - case Button.DOWN: - if (!this.starterIconsCursorObj.visible) { - if (currentRow < numOfRows - 1) { // not last row - if (currentRow - this.scrollCursor === 8) { // last row of visible starters - this.scrollCursor++; + this.starterIconsCursorObj.setVisible(false); + this.setSpecies(null); + this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1); + this.setFilterMode(true); + } else { + this.starterIconsCursorIndex--; + this.moveStarterIconsCursor(this.starterIconsCursorIndex); } - success = this.setCursor(this.cursor + 9); - this.updateScroll(); - } else if (numOfRows > 1) { - // DOWN from last row of Pokemon > Wrap around to first row - this.scrollCursor = 0; - this.updateScroll(); - success = this.setCursor(this.cursor % 9); - } else { - // DOWN from single row of Pokemon > Go to filters - this.filterBarCursor = this.filterBar.getNearestFilter(this.filteredStarterContainers[this.cursor]); - this.setFilterMode(true); success = true; } - } else { - if (this.starterIconsCursorIndex <= this.starterSpecies.length - 2) { - this.starterIconsCursorIndex++; - this.moveStarterIconsCursor(this.starterIconsCursorIndex); + break; + case Button.DOWN: + if (!this.starterIconsCursorObj.visible) { + if (currentRow < numOfRows - 1) { // not last row + if (currentRow - this.scrollCursor === 8) { // last row of visible starters + this.scrollCursor++; + } + success = this.setCursor(this.cursor + 9); + this.updateScroll(); + } else if (numOfRows > 1) { + // DOWN from last row of Pokemon > Wrap around to first row + this.scrollCursor = 0; + this.updateScroll(); + success = this.setCursor(this.cursor % 9); + } else { + // DOWN from single row of Pokemon > Go to filters + this.filterBarCursor = this.filterBar.getNearestFilter(this.filteredStarterContainers[this.cursor]); + this.setFilterMode(true); + success = true; + } } else { - this.starterIconsCursorObj.setVisible(false); - this.setSpecies(null); - this.startCursorObj.setVisible(true); + if (this.starterIconsCursorIndex <= this.starterSpecies.length - 2) { + this.starterIconsCursorIndex++; + this.moveStarterIconsCursor(this.starterIconsCursorIndex); + } else { + this.starterIconsCursorObj.setVisible(false); + this.setSpecies(null); + this.startCursorObj.setVisible(true); + } + success = true; } - success = true; - } - break; - case Button.LEFT: - if (!this.starterIconsCursorObj.visible) { - if (this.cursor % 9 !== 0) { - success = this.setCursor(this.cursor - 1); - } else { + break; + case Button.LEFT: + if (!this.starterIconsCursorObj.visible) { + if (this.cursor % 9 !== 0) { + success = this.setCursor(this.cursor - 1); + } else { // LEFT from filtered Pokemon, on the left edge - if (this.starterSpecies.length === 0) { + if (this.starterSpecies.length === 0) { // no starter in team > wrap around to the last column - success = this.setCursor(this.cursor + Math.min(8, numberOfStarters - this.cursor)); + success = this.setCursor(this.cursor + Math.min(8, numberOfStarters - this.cursor)); - } else if (onScreenCurrentRow < 7) { + } else if (onScreenCurrentRow < 7) { // at least one pokemon in team > for the first 7 rows, go to closest starter - this.cursorObj.setVisible(false); - this.starterIconsCursorIndex = findClosestStarterIndex(this.cursorObj.y - 1, this.starterSpecies.length); - this.moveStarterIconsCursor(this.starterIconsCursorIndex); + this.cursorObj.setVisible(false); + this.starterIconsCursorIndex = findClosestStarterIndex(this.cursorObj.y - 1, this.starterSpecies.length); + this.moveStarterIconsCursor(this.starterIconsCursorIndex); - } else { + } else { // at least one pokemon in team > from the bottom 2 rows, go to start run button - this.cursorObj.setVisible(false); - this.setSpecies(null); - this.startCursorObj.setVisible(true); + this.cursorObj.setVisible(false); + this.setSpecies(null); + this.startCursorObj.setVisible(true); + } + success = true; } - success = true; - } - } else if (numberOfStarters > 0) { + } else if (numberOfStarters > 0) { // LEFT from team > Go to closest filtered Pokemon - const closestRowIndex = findClosestStarterRow(this.starterIconsCursorIndex, onScreenNumberOfRows); - this.starterIconsCursorObj.setVisible(false); - this.cursorObj.setVisible(true); - this.setCursor(Math.min(onScreenFirstIndex + closestRowIndex * 9 + 8, onScreenLastIndex)); - success = true; - } else { - // LEFT from team and no Pokemon in filter > do nothing - success = false; - } - break; - case Button.RIGHT: - if (!this.starterIconsCursorObj.visible) { - // is not right edge - if (this.cursor % 9 < (currentRow < numOfRows - 1 ? 8 : (numberOfStarters - 1) % 9)) { - success = this.setCursor(this.cursor + 1); - } else { - // RIGHT from filtered Pokemon, on the right edge - if (this.starterSpecies.length === 0) { - // no selected starter in team > wrap around to the first column - success = this.setCursor(this.cursor - Math.min(8, this.cursor % 9)); - - } else if (onScreenCurrentRow < 7) { - // at least one pokemon in team > for the first 7 rows, go to closest starter - this.cursorObj.setVisible(false); - this.starterIconsCursorIndex = findClosestStarterIndex(this.cursorObj.y - 1, this.starterSpecies.length); - this.moveStarterIconsCursor(this.starterIconsCursorIndex); - - } else { - // at least one pokemon in team > from the bottom 2 rows, go to start run button - this.cursorObj.setVisible(false); - this.setSpecies(null); - this.startCursorObj.setVisible(true); - } + const closestRowIndex = findClosestStarterRow(this.starterIconsCursorIndex, onScreenNumberOfRows); + this.starterIconsCursorObj.setVisible(false); + this.cursorObj.setVisible(true); + this.setCursor(Math.min(onScreenFirstIndex + closestRowIndex * 9 + 8, onScreenLastIndex)); success = true; + } else { + // LEFT from team and no Pokemon in filter > do nothing + success = false; } - } else if (numberOfStarters > 0) { + break; + case Button.RIGHT: + if (!this.starterIconsCursorObj.visible) { + // is not right edge + if (this.cursor % 9 < (currentRow < numOfRows - 1 ? 8 : (numberOfStarters - 1) % 9)) { + success = this.setCursor(this.cursor + 1); + } else { + // RIGHT from filtered Pokemon, on the right edge + if (this.starterSpecies.length === 0) { + // no selected starter in team > wrap around to the first column + success = this.setCursor(this.cursor - Math.min(8, this.cursor % 9)); + + } else if (onScreenCurrentRow < 7) { + // at least one pokemon in team > for the first 7 rows, go to closest starter + this.cursorObj.setVisible(false); + this.starterIconsCursorIndex = findClosestStarterIndex(this.cursorObj.y - 1, this.starterSpecies.length); + this.moveStarterIconsCursor(this.starterIconsCursorIndex); + + } else { + // at least one pokemon in team > from the bottom 2 rows, go to start run button + this.cursorObj.setVisible(false); + this.setSpecies(null); + this.startCursorObj.setVisible(true); + } + success = true; + } + } else if (numberOfStarters > 0) { // RIGHT from team > Go to closest filtered Pokemon - const closestRowIndex = findClosestStarterRow(this.starterIconsCursorIndex, onScreenNumberOfRows); - this.starterIconsCursorObj.setVisible(false); - this.cursorObj.setVisible(true); - this.setCursor(Math.min(onScreenFirstIndex + closestRowIndex * 9, onScreenLastIndex - (onScreenLastIndex % 9))); - success = true; - } else { + const closestRowIndex = findClosestStarterRow(this.starterIconsCursorIndex, onScreenNumberOfRows); + this.starterIconsCursorObj.setVisible(false); + this.cursorObj.setVisible(true); + this.setCursor(Math.min(onScreenFirstIndex + closestRowIndex * 9, onScreenLastIndex - (onScreenLastIndex % 9))); + success = true; + } else { // RIGHT from team and no Pokemon in filter > do nothing - success = false; - } - break; + success = false; + } + break; } } } @@ -2126,7 +2132,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { break; } } - return [isDupe, removeIndex]; + return [ isDupe, removeIndex ]; } addToParty(species: PokemonSpecies, dexAttr: bigint, abilityIndex: integer, nature: Nature, moveset: StarterMoveset) { @@ -2204,29 +2210,29 @@ export default class StarterSelectUiHandler extends MessageUiHandler { if (gamepadType === "touch") { gamepadType = "keyboard"; switch (iconSetting) { - case SettingKeyboard.Button_Cycle_Shiny: - iconPath = "R.png"; - break; - case SettingKeyboard.Button_Cycle_Form: - iconPath = "F.png"; - break; - case SettingKeyboard.Button_Cycle_Gender: - iconPath = "G.png"; - break; - case SettingKeyboard.Button_Cycle_Ability: - iconPath = "E.png"; - break; - case SettingKeyboard.Button_Cycle_Nature: - iconPath = "N.png"; - break; - case SettingKeyboard.Button_Cycle_Variant: - iconPath = "V.png"; - break; - case SettingKeyboard.Button_Stats: - iconPath = "C.png"; - break; - default: - break; + case SettingKeyboard.Button_Cycle_Shiny: + iconPath = "R.png"; + break; + case SettingKeyboard.Button_Cycle_Form: + iconPath = "F.png"; + break; + case SettingKeyboard.Button_Cycle_Gender: + iconPath = "G.png"; + break; + case SettingKeyboard.Button_Cycle_Ability: + iconPath = "E.png"; + break; + case SettingKeyboard.Button_Cycle_Nature: + iconPath = "N.png"; + break; + case SettingKeyboard.Button_Cycle_Variant: + iconPath = "V.png"; + break; + case SettingKeyboard.Button_Stats: + iconPath = "C.png"; + break; + default: + break; } } else { iconPath = this.scene.inputController?.getIconForLatestInputRecorded(iconSetting); @@ -2236,7 +2242,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { controlLabel.setPosition(this.instructionRowX + this.instructionRowTextOffset, this.instructionRowY); iconElement.setVisible(true); controlLabel.setVisible(true); - this.instructionsContainer.add([iconElement, controlLabel]); + this.instructionsContainer.add([ iconElement, controlLabel ]); this.instructionRowY += 8; if (this.instructionRowY >= 24) { this.instructionRowY = 0; @@ -2259,7 +2265,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { controlLabel.setPosition(this.filterInstructionRowX + this.instructionRowTextOffset, this.filterInstructionRowY); iconElement.setVisible(true); controlLabel.setVisible(true); - this.filterInstructionsContainer.add([iconElement, controlLabel]); + this.filterInstructionsContainer.add([ iconElement, controlLabel ]); this.filterInstructionRowY += 8; if (this.filterInstructionRowY >= 24) { this.filterInstructionRowY = 0; @@ -2317,12 +2323,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler { getValueLimit(): integer { const valueLimit = new Utils.IntegerHolder(0); switch (this.scene.gameMode.modeId) { - case GameModes.ENDLESS: - case GameModes.SPLICED_ENDLESS: - valueLimit.value = 15; - break; - default: - valueLimit.value = 10; + case GameModes.ENDLESS: + case GameModes.SPLICED_ENDLESS: + valueLimit.value = 15; + break; + default: + valueLimit.value = 10; } Challenge.applyChallenges(this.scene.gameMode, Challenge.ChallengeType.STARTER_POINTS, valueLimit); @@ -2526,22 +2532,22 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const sort = this.filterBar.getVals(DropDownColumn.SORT)[0]; this.filteredStarterContainers.sort((a, b) => { switch (sort.val) { - default: - break; - case SortCriteria.NUMBER: - return (a.species.speciesId - b.species.speciesId) * -sort.dir; - case SortCriteria.COST: - return (a.cost - b.cost) * -sort.dir; - case SortCriteria.CANDY: - const candyCountA = this.scene.gameData.starterData[a.species.speciesId].candyCount; - const candyCountB = this.scene.gameData.starterData[b.species.speciesId].candyCount; - return (candyCountA - candyCountB) * -sort.dir; - case SortCriteria.IV: - const avgIVsA = this.scene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[a.species.speciesId].ivs.length; - const avgIVsB = this.scene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[b.species.speciesId].ivs.length; - return (avgIVsA - avgIVsB) * -sort.dir; - case SortCriteria.NAME: - return a.species.name.localeCompare(b.species.name) * -sort.dir; + default: + break; + case SortCriteria.NUMBER: + return (a.species.speciesId - b.species.speciesId) * -sort.dir; + case SortCriteria.COST: + return (a.cost - b.cost) * -sort.dir; + case SortCriteria.CANDY: + const candyCountA = this.scene.gameData.starterData[a.species.speciesId].candyCount; + const candyCountB = this.scene.gameData.starterData[b.species.speciesId].candyCount; + return (candyCountA - candyCountB) * -sort.dir; + case SortCriteria.IV: + const avgIVsA = this.scene.gameData.dexData[a.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[a.species.speciesId].ivs.length; + const avgIVsB = this.scene.gameData.dexData[b.species.speciesId].ivs.reduce((a, b) => a + b, 0) / this.scene.gameData.dexData[b.species.speciesId].ivs.length; + return (avgIVsA - avgIVsB) * -sort.dir; + case SortCriteria.NAME: + return a.species.name.localeCompare(b.species.name) * -sort.dir; } return 0; }); @@ -2553,7 +2559,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const maxColumns = 9; const maxRows = 9; const onScreenFirstIndex = this.scrollCursor * maxColumns; - const onScreenLastIndex = Math.min(this.filteredStarterContainers.length - 1, onScreenFirstIndex + maxRows * maxColumns -1); + const onScreenLastIndex = Math.min(this.filteredStarterContainers.length - 1, onScreenFirstIndex + maxRows * maxColumns - 1); this.starterSelectScrollBar.setScrollCursor(this.scrollCursor); @@ -2656,9 +2662,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonShinyIcon.setTint(tint); this.setSpecies(species); this.updateInstructions(); - } else { - console.warn("Species is undefined for cursor position", cursor); - this.setFilterMode(true); } } @@ -2719,7 +2722,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.pokemonAbilityText.off("pointerover"); this.pokemonPassiveText.off("pointerover"); - const starterAttributes : StarterAttributes | null = species ? {...this.starterPreferences[species.speciesId]} : null; + const starterAttributes : StarterAttributes | null = species ? { ...this.starterPreferences[species.speciesId] } : null; if (starterAttributes?.nature) { // load default nature from stater save data, if set @@ -2778,7 +2781,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { let growthReadable = Utils.toReadableString(GrowthRate[species.growthRate]); const growthAux = growthReadable.replace(" ", "_"); if (i18next.exists("growth:" + growthAux)) { - growthReadable = i18next.t("growth:"+ growthAux as any); + growthReadable = i18next.t("growth:" + growthAux as any); } this.pokemonGrowthRateText.setText(growthReadable); @@ -2951,7 +2954,6 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } - setSpeciesDetails(species: PokemonSpecies, shiny?: boolean, formIndex?: integer, female?: boolean, variant?: Variant, abilityIndex?: integer, natureIndex?: integer, forSeen: boolean = false): void { const oldProps = species ? this.scene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor) : null; const oldAbilityIndex = this.abilityCursor > -1 ? this.abilityCursor : this.scene.gameData.getStarterSpeciesDefaultAbilityIndex(species); @@ -2961,8 +2963,12 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.natureCursor = -1; if (this.activeTooltip === "CANDY") { - const { currentFriendship, friendshipCap } = this.getFriendship(this.lastSpecies.speciesId); - this.scene.ui.editTooltip("", `${currentFriendship}/${friendshipCap}`); + if (this.lastSpecies) { + const { currentFriendship, friendshipCap } = this.getFriendship(this.lastSpecies.speciesId); + this.scene.ui.editTooltip("", `${currentFriendship}/${friendshipCap}`); + } else { + this.scene.ui.hideTooltip(); + } } if (species?.forms?.find(f => f.formKey === "female")) { @@ -2980,7 +2986,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.dexAttrCursor |= this.scene.gameData.getFormAttr(formIndex !== undefined ? formIndex : (formIndex = oldProps!.formIndex)); // TODO: is this bang correct? this.abilityCursor = abilityIndex !== undefined ? abilityIndex : (abilityIndex = oldAbilityIndex); this.natureCursor = natureIndex !== undefined ? natureIndex : (natureIndex = oldNatureIndex); - const [isInParty, partyIndex]: [boolean, number] = this.isInParty(species); // we use this to firstly check if the pokemon is in the party, and if so, to get the party index in order to update the icon image + const [ isInParty, partyIndex ]: [boolean, number] = this.isInParty(species); // we use this to firstly check if the pokemon is in the party, and if so, to get the party index in order to update the icon image if (isInParty) { this.updatePartyIcon(species, partyIndex); } @@ -3077,7 +3083,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { const isVariant3Caught = isShinyCaught && !!(caughtAttr & DexAttr.VARIANT_3); this.canCycleShiny = isNonShinyCaught && isShinyCaught; - this.canCycleVariant = !!shiny && [ isVariant1Caught, isVariant2Caught, isVariant3Caught].filter(v => v).length > 1; + this.canCycleVariant = !!shiny && [ isVariant1Caught, isVariant2Caught, isVariant3Caught ].filter(v => v).length > 1; const isMaleCaught = !!(caughtAttr & DexAttr.MALE); const isFemaleCaught = !!(caughtAttr & DexAttr.FEMALE); @@ -3327,6 +3333,18 @@ export default class StarterSelectUiHandler extends MessageUiHandler { } } this.moveStarterIconsCursor(this.starterIconsCursorIndex); + } else if (this.startCursorObj.visible && this.starterSpecies.length === 0) { + // On the start button and no more Pokemon in party + this.startCursorObj.setVisible(false); + if (this.filteredStarterContainers.length > 0) { + // Back to the first Pokemon if there is one + this.cursorObj.setVisible(true); + this.setCursor(0 + this.scrollCursor * 9); + } else { + // Back to filters + this.filterBarCursor = Math.max(1, this.filterBar.numFilters - 1); + this.setFilterMode(true); + } } this.tryUpdateValue(); @@ -3344,16 +3362,16 @@ export default class StarterSelectUiHandler extends MessageUiHandler { starter.label.setText(valueStr); let textStyle: TextStyle; switch (baseStarterValue - starterValue) { - case 0: - textStyle = TextStyle.WINDOW; - break; - case 1: - case 0.5: - textStyle = TextStyle.SUMMARY_BLUE; - break; - default: - textStyle = TextStyle.SUMMARY_GOLD; - break; + case 0: + textStyle = TextStyle.WINDOW; + break; + case 1: + case 0.5: + textStyle = TextStyle.SUMMARY_BLUE; + break; + default: + textStyle = TextStyle.SUMMARY_GOLD; + break; } if (baseStarterValue - starterValue > 0) { starter.label.setColor(this.getTextColor(textStyle)); @@ -3456,6 +3474,7 @@ export default class StarterSelectUiHandler extends MessageUiHandler { this.scene.clearPhaseQueue(); if (this.scene.gameMode.isChallenge) { this.scene.pushPhase(new SelectChallengePhase(this.scene)); + this.scene.pushPhase(new EncounterPhase(this.scene, false)); } else { this.scene.pushPhase(new TitlePhase(this.scene)); } @@ -3640,6 +3659,9 @@ export default class StarterSelectUiHandler extends MessageUiHandler { StarterPrefs.save(this.starterPreferences); this.cursor = -1; this.hideInstructions(); + this.activeTooltip = undefined; + this.scene.ui.hideTooltip(); + this.starterSelectContainer.setVisible(false); this.blockInput = false; diff --git a/src/ui/stats-container.ts b/src/ui/stats-container.ts index 06dd6e7c035..7e026ede83e 100644 --- a/src/ui/stats-container.ts +++ b/src/ui/stats-container.ts @@ -6,12 +6,12 @@ import i18next from "i18next"; const ivChartSize = 24; -const ivChartStatCoordMultipliers = [[0, -1], [0.825, -0.5], [0.825, 0.5], [-0.825, -0.5], [-0.825, 0.5], [0, 1]]; +const ivChartStatCoordMultipliers = [[ 0, -1 ], [ 0.825, -0.5 ], [ 0.825, 0.5 ], [ -0.825, -0.5 ], [ -0.825, 0.5 ], [ 0, 1 ]]; const speedLabelOffset = -3; const sideLabelOffset = 1; -const ivLabelOffset = [0, sideLabelOffset, -sideLabelOffset, sideLabelOffset, -sideLabelOffset, speedLabelOffset]; -const ivChartLabelyOffset= [0, 5, 0, 5, 0, 0]; // doing this so attack does not overlap with (+N) -const ivChartStatIndexes = [0, 1, 2, 5, 4, 3]; // swap special attack and speed +const ivLabelOffset = [ 0, sideLabelOffset, -sideLabelOffset, sideLabelOffset, -sideLabelOffset, speedLabelOffset ]; +const ivChartLabelyOffset = [ 0, 5, 0, 5, 0, 0 ]; // doing this so attack does not overlap with (+N) +const ivChartStatIndexes = [ 0, 1, 2, 5, 4, 3 ]; // swap special attack and speed const defaultIvChartData = new Array(12).fill(null).map(() => 0); @@ -39,7 +39,7 @@ export class StatsContainer extends Phaser.GameObjects.Container { .setStrokeStyle(1, 0x484050); ivChartBorder.setOrigin(0, 0); - const ivChartBgLines = [ [ 0, -1, 0, 1 ], [ -0.825, -0.5, 0.825, 0.5 ], [ 0.825, -0.5, -0.825, 0.5 ] ].map(coords => { + const ivChartBgLines = [[ 0, -1, 0, 1 ], [ -0.825, -0.5, 0.825, 0.5 ], [ 0.825, -0.5, -0.825, 0.5 ]].map(coords => { const line = new Phaser.GameObjects.Line(this.scene, ivChartBg.x, ivChartBg.y, ivChartSize * coords[0], ivChartSize * coords[1], ivChartSize * coords[2], ivChartSize * coords[3], 0xffffff) .setLineWidth(0.5); line.setOrigin(0, 0); diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index d3985b225ff..b35c0ca3303 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -406,22 +406,22 @@ export default class SummaryUiHandler extends UiHandler { this.genderText.setShadowColor(getGenderColor(this.pokemon.getGender(true), true)); switch (this.summaryUiMode) { - case SummaryUiMode.DEFAULT: - const page = args.length < 2 ? Page.PROFILE : args[2] as Page; - this.hideMoveEffect(true); - this.setCursor(page); - if (args.length > 3) { - this.selectCallback = args[3]; - } - break; - case SummaryUiMode.LEARN_MOVE: - this.newMove = args[2] as Move; - this.moveSelectFunction = args[3] as Function; + case SummaryUiMode.DEFAULT: + const page = args.length < 2 ? Page.PROFILE : args[2] as Page; + this.hideMoveEffect(true); + this.setCursor(page); + if (args.length > 3) { + this.selectCallback = args[3]; + } + break; + case SummaryUiMode.LEARN_MOVE: + this.newMove = args[2] as Move; + this.moveSelectFunction = args[3] as Function; - this.showMoveEffect(true); - this.setCursor(Page.MOVES); - this.showMoveSelect(); - break; + this.showMoveEffect(true); + this.setCursor(Page.MOVES); + this.showMoveSelect(); + break; } const fromSummary = args.length >= 2; @@ -489,25 +489,25 @@ export default class SummaryUiHandler extends UiHandler { success = true; } else { switch (button) { - case Button.UP: - success = this.setCursor(this.moveCursor ? this.moveCursor - 1 : 4); - break; - case Button.DOWN: - success = this.setCursor(this.moveCursor < 4 ? this.moveCursor + 1 : 0); - break; - case Button.LEFT: - this.moveSelect = false; - this.setCursor(Page.STATS); - if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { - this.hideMoveEffect(); - this.destroyBlinkCursor(); - success = true; + case Button.UP: + success = this.setCursor(this.moveCursor ? this.moveCursor - 1 : 4); break; - } else { - this.hideMoveSelect(); - success = true; + case Button.DOWN: + success = this.setCursor(this.moveCursor < 4 ? this.moveCursor + 1 : 0); break; - } + case Button.LEFT: + this.moveSelect = false; + this.setCursor(Page.STATS); + if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { + this.hideMoveEffect(); + this.destroyBlinkCursor(); + success = true; + break; + } else { + this.hideMoveSelect(); + success = true; + break; + } } } } else { @@ -546,35 +546,35 @@ export default class SummaryUiHandler extends UiHandler { } else { const pages = Utils.getEnumValues(Page); switch (button) { - case Button.UP: - case Button.DOWN: - if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { - break; - } else if (!fromPartyMode) { - break; - } - const isDown = button === Button.DOWN; - const party = this.scene.getParty(); - const partyMemberIndex = this.pokemon ? party.indexOf(this.pokemon) : -1; - if ((isDown && partyMemberIndex < party.length - 1) || (!isDown && partyMemberIndex)) { - const page = this.cursor; - this.clear(); - this.show([ party[partyMemberIndex + (isDown ? 1 : -1)], this.summaryUiMode, page ]); - } - break; - case Button.LEFT: - if (this.cursor) { - success = this.setCursor(this.cursor - 1); - } - break; - case Button.RIGHT: - if (this.cursor < pages.length - 1) { - success = this.setCursor(this.cursor + 1); - if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.cursor === Page.MOVES) { - this.moveSelect = true; + case Button.UP: + case Button.DOWN: + if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { + break; + } else if (!fromPartyMode) { + break; } - } - break; + const isDown = button === Button.DOWN; + const party = this.scene.getParty(); + const partyMemberIndex = this.pokemon ? party.indexOf(this.pokemon) : -1; + if ((isDown && partyMemberIndex < party.length - 1) || (!isDown && partyMemberIndex)) { + const page = this.cursor; + this.clear(); + this.show([ party[partyMemberIndex + (isDown ? 1 : -1)], this.summaryUiMode, page ]); + } + break; + case Button.LEFT: + if (this.cursor) { + success = this.setCursor(this.cursor - 1); + } + break; + case Button.RIGHT: + if (this.cursor < pages.length - 1) { + success = this.setCursor(this.cursor + 1); + if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.cursor === Page.MOVES) { + this.moveSelect = true; + } + } + break; } } } @@ -685,7 +685,7 @@ export default class SummaryUiHandler extends UiHandler { onComplete: () => { if (forward) { this.populatePageContainer(this.summaryPageContainer); - if (this.cursor===Page.MOVES) { + if (this.cursor === Page.MOVES) { this.moveCursorObj = null; this.showMoveSelect(); this.showMoveEffect(); @@ -730,308 +730,308 @@ export default class SummaryUiHandler extends UiHandler { } switch (page) { - case Page.PROFILE: - const profileContainer = this.scene.add.container(0, -pageBg.height); - pageContainer.add(profileContainer); + case Page.PROFILE: + const profileContainer = this.scene.add.container(0, -pageBg.height); + pageContainer.add(profileContainer); - // TODO: should add field for original trainer name to Pokemon object, to support gift/traded Pokemon from MEs - const trainerText = addBBCodeTextObject(this.scene, 7, 12, `${i18next.t("pokemonSummary:ot")}/${getBBCodeFrag(loggedInUser?.username || i18next.t("pokemonSummary:unknown"), this.scene.gameData.gender === PlayerGender.FEMALE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE)}`, TextStyle.SUMMARY_ALT); - trainerText.setOrigin(0, 0); - profileContainer.add(trainerText); + // TODO: should add field for original trainer name to Pokemon object, to support gift/traded Pokemon from MEs + const trainerText = addBBCodeTextObject(this.scene, 7, 12, `${i18next.t("pokemonSummary:ot")}/${getBBCodeFrag(loggedInUser?.username || i18next.t("pokemonSummary:unknown"), this.scene.gameData.gender === PlayerGender.FEMALE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE)}`, TextStyle.SUMMARY_ALT); + trainerText.setOrigin(0, 0); + profileContainer.add(trainerText); - const trainerIdText = addTextObject(this.scene, 174, 12, this.scene.gameData.trainerId.toString(), TextStyle.SUMMARY_ALT); - trainerIdText.setOrigin(0, 0); - profileContainer.add(trainerIdText); + const trainerIdText = addTextObject(this.scene, 174, 12, this.scene.gameData.trainerId.toString(), TextStyle.SUMMARY_ALT); + trainerIdText.setOrigin(0, 0); + profileContainer.add(trainerIdText); - const typeLabel = addTextObject(this.scene, 7, 28, `${i18next.t("pokemonSummary:type")}/`, TextStyle.WINDOW_ALT); - typeLabel.setOrigin(0, 0); - profileContainer.add(typeLabel); + const typeLabel = addTextObject(this.scene, 7, 28, `${i18next.t("pokemonSummary:type")}/`, TextStyle.WINDOW_ALT); + typeLabel.setOrigin(0, 0); + profileContainer.add(typeLabel); - const getTypeIcon = (index: integer, type: Type, tera: boolean = false) => { - const xCoord = typeLabel.width * typeLabel.scale + 9 + 34 * index; - const typeIcon = !tera - ? this.scene.add.sprite(xCoord, 42, Utils.getLocalizedSpriteKey("types"), Type[type].toLowerCase()) - : this.scene.add.sprite(xCoord, 42, "type_tera"); - if (tera) { - typeIcon.setScale(0.5); - const typeRgb = getTypeRgb(type); - typeIcon.setTint(Phaser.Display.Color.GetColor(typeRgb[0], typeRgb[1], typeRgb[2])); - } - typeIcon.setOrigin(0, 1); - return typeIcon; - }; - - const types = this.pokemon?.getTypes(false, false, true)!; // TODO: is this bang correct? - profileContainer.add(getTypeIcon(0, types[0])); - if (types.length > 1) { - profileContainer.add(getTypeIcon(1, types[1])); - } - if (this.pokemon?.isTerastallized()) { - profileContainer.add(getTypeIcon(types.length, this.pokemon.getTeraType(), true)); - } - - if (this.pokemon?.getLuck()) { - const luckLabelText = addTextObject(this.scene, 141, 28, i18next.t("common:luckIndicator"), TextStyle.SUMMARY_ALT); - luckLabelText.setOrigin(0, 0); - profileContainer.add(luckLabelText); - - const luckText = addTextObject(this.scene, 141 + luckLabelText.displayWidth + 2, 28, this.pokemon.getLuck().toString(), TextStyle.SUMMARY); - luckText.setOrigin(0, 0); - luckText.setTint(getVariantTint((Math.min(this.pokemon.getLuck() - 1, 2)) as Variant)); - profileContainer.add(luckText); - } - - this.abilityContainer = { - labelImage: this.scene.add.image(0, 0, "summary_profile_ability"), - ability: this.pokemon?.getAbility(true)!, // TODO: is this bang correct? - nameText: null, - descriptionText: null}; - - const allAbilityInfo = [this.abilityContainer]; // Creates an array to iterate through - // Only add to the array and set up displaying a passive if it's unlocked - if (this.pokemon?.hasPassive()) { - this.passiveContainer = { - labelImage: this.scene.add.image(0, 0, "summary_profile_passive"), - ability: this.pokemon.getPassiveAbility(), - nameText: null, - descriptionText: null}; - allAbilityInfo.push(this.passiveContainer); - - // Sets up the pixel button prompt image - this.abilityPrompt = this.scene.add.image(0, 0, !this.scene.inputController?.gamepadSupport ? "summary_profile_prompt_z" : "summary_profile_prompt_a"); - this.abilityPrompt.setPosition(8, 43); - this.abilityPrompt.setVisible(true); - this.abilityPrompt.setOrigin(0, 0); - profileContainer.add(this.abilityPrompt); - } - - allAbilityInfo.forEach(abilityInfo => { - abilityInfo.labelImage.setPosition(17, 43); - abilityInfo.labelImage.setVisible(true); - abilityInfo.labelImage.setOrigin(0, 0); - profileContainer.add(abilityInfo.labelImage); - - abilityInfo.nameText = addTextObject(this.scene, 7, 66, abilityInfo.ability?.name!, TextStyle.SUMMARY_ALT); // TODO: is this bang correct? - abilityInfo.nameText.setOrigin(0, 1); - profileContainer.add(abilityInfo.nameText); - - abilityInfo.descriptionText = addTextObject(this.scene, 7, 69, abilityInfo.ability?.description!, TextStyle.WINDOW_ALT, { wordWrap: { width: 1224 } }); // TODO: is this bang correct? - abilityInfo.descriptionText.setOrigin(0, 0); - profileContainer.add(abilityInfo.descriptionText); - - // Sets up the mask that hides the description text to give an illusion of scrolling - const descriptionTextMaskRect = this.scene.make.graphics({}); - descriptionTextMaskRect.setScale(6); - descriptionTextMaskRect.fillStyle(0xFFFFFF); - descriptionTextMaskRect.beginPath(); - descriptionTextMaskRect.fillRect(110, 90.5, 206, 31); - - const abilityDescriptionTextMask = descriptionTextMaskRect.createGeometryMask(); - - abilityInfo.descriptionText.setMask(abilityDescriptionTextMask); - - const abilityDescriptionLineCount = Math.floor(abilityInfo.descriptionText.displayHeight / 14.83); - - // Animates the description text moving upwards - if (abilityDescriptionLineCount > 2) { - abilityInfo.descriptionText.setY(69); - this.descriptionScrollTween = this.scene.tweens.add({ - targets: abilityInfo.descriptionText, - delay: Utils.fixedInt(2000), - loop: -1, - hold: Utils.fixedInt(2000), - duration: Utils.fixedInt((abilityDescriptionLineCount - 2) * 2000), - y: `-=${14.83 * (abilityDescriptionLineCount - 2)}` - }); - } - }); - // Turn off visibility of passive info by default - this.passiveContainer?.labelImage.setVisible(false); - this.passiveContainer?.nameText?.setVisible(false); - this.passiveContainer?.descriptionText?.setVisible(false); - - const closeFragment = getBBCodeFrag("", TextStyle.WINDOW_ALT); - const rawNature = Utils.toReadableString(Nature[this.pokemon?.getNature()!]); // TODO: is this bang correct? - const nature = `${getBBCodeFrag(Utils.toReadableString(getNatureName(this.pokemon?.getNature()!)), TextStyle.SUMMARY_RED)}${closeFragment}`; // TODO: is this bang correct? - - const memoString = i18next.t("pokemonSummary:memoString", { - metFragment: i18next.t(`pokemonSummary:metFragment.${this.pokemon?.metBiome === -1? "apparently": "normal"}`, { - biome: `${getBBCodeFrag(getBiomeName(this.pokemon?.metBiome!), TextStyle.SUMMARY_RED)}${closeFragment}`, // TODO: is this bang correct? - level: `${getBBCodeFrag(this.pokemon?.metLevel.toString()!, TextStyle.SUMMARY_RED)}${closeFragment}`, // TODO: is this bang correct? - wave: `${getBBCodeFrag((this.pokemon?.metWave ? this.pokemon.metWave.toString()! : i18next.t("pokemonSummary:unknownTrainer")), TextStyle.SUMMARY_RED)}${closeFragment}`, - }), - natureFragment: i18next.t(`pokemonSummary:natureFragment.${rawNature}`, { nature: nature }) - }); - - const memoText = addBBCodeTextObject(this.scene, 7, 113, String(memoString), TextStyle.WINDOW_ALT); - memoText.setOrigin(0, 0); - profileContainer.add(memoText); - break; - case Page.STATS: - const statsContainer = this.scene.add.container(0, -pageBg.height); - pageContainer.add(statsContainer); - - PERMANENT_STATS.forEach((stat, s) => { - const statName = i18next.t(getStatKey(stat)); - const rowIndex = s % 3; - const colIndex = Math.floor(s / 3); - - const natureStatMultiplier = getNatureStatMultiplier(this.pokemon?.getNature()!, s); // TODO: is this bang correct? - - const statLabel = addTextObject(this.scene, 27 + 115 * colIndex + (colIndex === 1 ? 5 : 0), 56 + 16 * rowIndex, statName, natureStatMultiplier === 1 ? TextStyle.SUMMARY : natureStatMultiplier > 1 ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE); - statLabel.setOrigin(0.5, 0); - statsContainer.add(statLabel); - - const statValueText = stat !== Stat.HP - ? Utils.formatStat(this.pokemon?.getStat(stat)!) // TODO: is this bang correct? - : `${Utils.formatStat(this.pokemon?.hp!, true)}/${Utils.formatStat(this.pokemon?.getMaxHp()!, true)}`; // TODO: are those bangs correct? - - const statValue = addTextObject(this.scene, 120 + 88 * colIndex, 56 + 16 * rowIndex, statValueText, TextStyle.WINDOW_ALT); - statValue.setOrigin(1, 0); - statsContainer.add(statValue); - }); - - const itemModifiers = (this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier - && m.pokemonId === this.pokemon?.id, this.playerParty) as PokemonHeldItemModifier[]) - .sort(modifierSortFunc); - - itemModifiers.forEach((item, i) => { - const icon = item.getIcon(this.scene, true); - - icon.setPosition((i % 17) * 12 + 3, 14 * Math.floor(i / 17) + 15); - statsContainer.add(icon); - - icon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 32, 32), Phaser.Geom.Rectangle.Contains); - icon.on("pointerover", () => (this.scene as BattleScene).ui.showTooltip(item.type.name, item.type.getDescription(this.scene), true)); - icon.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip()); - }); - - const pkmLvl = this.pokemon?.level!; // TODO: is this bang correct? - const pkmLvlExp = this.pokemon?.levelExp!; // TODO: is this bang correct? - const pkmExp = this.pokemon?.exp!; // TODO: is this bang correct? - const pkmSpeciesGrowthRate = this.pokemon?.species.growthRate!; // TODO: is this bang correct? - const relLvExp = getLevelRelExp(pkmLvl + 1, pkmSpeciesGrowthRate); - const expRatio = pkmLvl < this.scene.getMaxExpLevel() ? pkmLvlExp / relLvExp : 0; - - const expLabel = addTextObject(this.scene, 6, 112, i18next.t("pokemonSummary:expPoints"), TextStyle.SUMMARY); - expLabel.setOrigin(0, 0); - statsContainer.add(expLabel); - - const nextLvExpLabel = addTextObject(this.scene, 6, 128, i18next.t("pokemonSummary:nextLv"), TextStyle.SUMMARY); - nextLvExpLabel.setOrigin(0, 0); - statsContainer.add(nextLvExpLabel); - - const expText = addTextObject(this.scene, 208, 112, pkmExp.toString(), TextStyle.WINDOW_ALT); - expText.setOrigin(1, 0); - statsContainer.add(expText); - - const nextLvExp = pkmLvl < this.scene.getMaxExpLevel() - ? getLevelTotalExp(pkmLvl + 1, pkmSpeciesGrowthRate) - pkmExp - : 0; - const nextLvExpText = addTextObject(this.scene, 208, 128, nextLvExp.toString(), TextStyle.WINDOW_ALT); - nextLvExpText.setOrigin(1, 0); - statsContainer.add(nextLvExpText); - - const expOverlay = this.scene.add.image(140, 145, "summary_stats_overlay_exp"); - expOverlay.setOrigin(0, 0); - statsContainer.add(expOverlay); - - const expMaskRect = this.scene.make.graphics({}); - expMaskRect.setScale(6); - expMaskRect.fillStyle(0xFFFFFF); - expMaskRect.beginPath(); - expMaskRect.fillRect(140 + pageContainer.x, 145 + pageContainer.y + 21, Math.floor(expRatio * 64), 3); - - const expMask = expMaskRect.createGeometryMask(); - - expOverlay.setMask(expMask); - break; - case Page.MOVES: - this.movesContainer = this.scene.add.container(5, -pageBg.height + 26); - pageContainer.add(this.movesContainer); - - this.extraMoveRowContainer = this.scene.add.container(0, 64); - this.extraMoveRowContainer.setVisible(false); - this.movesContainer.add(this.extraMoveRowContainer); - - const extraRowOverlay = this.scene.add.image(-2, 1, "summary_moves_overlay_row"); - extraRowOverlay.setOrigin(0, 1); - this.extraMoveRowContainer.add(extraRowOverlay); - - const extraRowText = addTextObject(this.scene, 35, 0, this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.newMove ? this.newMove.name : i18next.t("pokemonSummary:cancel"), - this.summaryUiMode === SummaryUiMode.LEARN_MOVE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY); - extraRowText.setOrigin(0, 1); - this.extraMoveRowContainer.add(extraRowText); - - if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { - this.extraMoveRowContainer.setVisible(true); - - if (this.newMove && this.pokemon) { - const spriteKey = Utils.getLocalizedSpriteKey("types"); - const moveType = this.pokemon.getMoveType(this.newMove); - const newMoveTypeIcon = this.scene.add.sprite(0, 0, spriteKey, Type[moveType].toLowerCase()); - newMoveTypeIcon.setOrigin(0, 1); - this.extraMoveRowContainer.add(newMoveTypeIcon); - } - const ppOverlay = this.scene.add.image(163, -1, "summary_moves_overlay_pp"); - ppOverlay.setOrigin(0, 1); - this.extraMoveRowContainer.add(ppOverlay); - - const pp = Utils.padInt(this.newMove?.pp!, 2, " "); // TODO: is this bang correct? - const ppText = addTextObject(this.scene, 173, 1, `${pp}/${pp}`, TextStyle.WINDOW); - ppText.setOrigin(0, 1); - this.extraMoveRowContainer.add(ppText); - } - - this.moveRowsContainer = this.scene.add.container(0, 0); - this.movesContainer.add(this.moveRowsContainer); - - for (let m = 0; m < 4; m++) { - const move: PokemonMove | null = this.pokemon && this.pokemon.moveset.length > m ? this.pokemon?.moveset[m] : null; - const moveRowContainer = this.scene.add.container(0, 16 * m); - this.moveRowsContainer.add(moveRowContainer); - - if (move && this.pokemon) { - const spriteKey = Utils.getLocalizedSpriteKey("types"); - const moveType = this.pokemon.getMoveType(move.getMove()); - const typeIcon = this.scene.add.sprite(0, 0, spriteKey, Type[moveType].toLowerCase()); + const getTypeIcon = (index: integer, type: Type, tera: boolean = false) => { + const xCoord = typeLabel.width * typeLabel.scale + 9 + 34 * index; + const typeIcon = !tera + ? this.scene.add.sprite(xCoord, 42, Utils.getLocalizedSpriteKey("types"), Type[type].toLowerCase()) + : this.scene.add.sprite(xCoord, 42, "type_tera"); + if (tera) { + typeIcon.setScale(0.5); + const typeRgb = getTypeRgb(type); + typeIcon.setTint(Phaser.Display.Color.GetColor(typeRgb[0], typeRgb[1], typeRgb[2])); + } typeIcon.setOrigin(0, 1); - moveRowContainer.add(typeIcon); + return typeIcon; + }; + + const types = this.pokemon?.getTypes(false, false, true)!; // TODO: is this bang correct? + profileContainer.add(getTypeIcon(0, types[0])); + if (types.length > 1) { + profileContainer.add(getTypeIcon(1, types[1])); + } + if (this.pokemon?.isTerastallized()) { + profileContainer.add(getTypeIcon(types.length, this.pokemon.getTeraType(), true)); } - const moveText = addTextObject(this.scene, 35, 0, move ? move.getName() : "-", TextStyle.SUMMARY); - moveText.setOrigin(0, 1); - moveRowContainer.add(moveText); + if (this.pokemon?.getLuck()) { + const luckLabelText = addTextObject(this.scene, 141, 28, i18next.t("common:luckIndicator"), TextStyle.SUMMARY_ALT); + luckLabelText.setOrigin(0, 0); + profileContainer.add(luckLabelText); - const ppOverlay = this.scene.add.image(163, -1, "summary_moves_overlay_pp"); - ppOverlay.setOrigin(0, 1); - moveRowContainer.add(ppOverlay); - - const ppText = addTextObject(this.scene, 173, 1, "--/--", TextStyle.WINDOW); - ppText.setOrigin(0, 1); - - if (move) { - const maxPP = move.getMovePp(); - const pp = maxPP - move.ppUsed; - ppText.setText(`${Utils.padInt(pp, 2, " ")}/${Utils.padInt(maxPP, 2, " ")}`); + const luckText = addTextObject(this.scene, 141 + luckLabelText.displayWidth + 2, 28, this.pokemon.getLuck().toString(), TextStyle.SUMMARY); + luckText.setOrigin(0, 0); + luckText.setTint(getVariantTint((Math.min(this.pokemon.getLuck() - 1, 2)) as Variant)); + profileContainer.add(luckText); } - moveRowContainer.add(ppText); - } + this.abilityContainer = { + labelImage: this.scene.add.image(0, 0, "summary_profile_ability"), + ability: this.pokemon?.getAbility(true)!, // TODO: is this bang correct? + nameText: null, + descriptionText: null }; - this.moveDescriptionText = addTextObject(this.scene, 2, 84, "", TextStyle.WINDOW_ALT, { wordWrap: { width: 1212 } }); - this.movesContainer.add(this.moveDescriptionText); + const allAbilityInfo = [ this.abilityContainer ]; // Creates an array to iterate through + // Only add to the array and set up displaying a passive if it's unlocked + if (this.pokemon?.hasPassive()) { + this.passiveContainer = { + labelImage: this.scene.add.image(0, 0, "summary_profile_passive"), + ability: this.pokemon.getPassiveAbility(), + nameText: null, + descriptionText: null }; + allAbilityInfo.push(this.passiveContainer); - const moveDescriptionTextMaskRect = this.scene.make.graphics({}); - moveDescriptionTextMaskRect.setScale(6); - moveDescriptionTextMaskRect.fillStyle(0xFFFFFF); - moveDescriptionTextMaskRect.beginPath(); - moveDescriptionTextMaskRect.fillRect(112, 130, 202, 46); + // Sets up the pixel button prompt image + this.abilityPrompt = this.scene.add.image(0, 0, !this.scene.inputController?.gamepadSupport ? "summary_profile_prompt_z" : "summary_profile_prompt_a"); + this.abilityPrompt.setPosition(8, 43); + this.abilityPrompt.setVisible(true); + this.abilityPrompt.setOrigin(0, 0); + profileContainer.add(this.abilityPrompt); + } - const moveDescriptionTextMask = moveDescriptionTextMaskRect.createGeometryMask(); + allAbilityInfo.forEach(abilityInfo => { + abilityInfo.labelImage.setPosition(17, 43); + abilityInfo.labelImage.setVisible(true); + abilityInfo.labelImage.setOrigin(0, 0); + profileContainer.add(abilityInfo.labelImage); - this.moveDescriptionText.setMask(moveDescriptionTextMask); - break; + abilityInfo.nameText = addTextObject(this.scene, 7, 66, abilityInfo.ability?.name!, TextStyle.SUMMARY_ALT); // TODO: is this bang correct? + abilityInfo.nameText.setOrigin(0, 1); + profileContainer.add(abilityInfo.nameText); + + abilityInfo.descriptionText = addTextObject(this.scene, 7, 69, abilityInfo.ability?.description!, TextStyle.WINDOW_ALT, { wordWrap: { width: 1224 }}); // TODO: is this bang correct? + abilityInfo.descriptionText.setOrigin(0, 0); + profileContainer.add(abilityInfo.descriptionText); + + // Sets up the mask that hides the description text to give an illusion of scrolling + const descriptionTextMaskRect = this.scene.make.graphics({}); + descriptionTextMaskRect.setScale(6); + descriptionTextMaskRect.fillStyle(0xFFFFFF); + descriptionTextMaskRect.beginPath(); + descriptionTextMaskRect.fillRect(110, 90.5, 206, 31); + + const abilityDescriptionTextMask = descriptionTextMaskRect.createGeometryMask(); + + abilityInfo.descriptionText.setMask(abilityDescriptionTextMask); + + const abilityDescriptionLineCount = Math.floor(abilityInfo.descriptionText.displayHeight / 14.83); + + // Animates the description text moving upwards + if (abilityDescriptionLineCount > 2) { + abilityInfo.descriptionText.setY(69); + this.descriptionScrollTween = this.scene.tweens.add({ + targets: abilityInfo.descriptionText, + delay: Utils.fixedInt(2000), + loop: -1, + hold: Utils.fixedInt(2000), + duration: Utils.fixedInt((abilityDescriptionLineCount - 2) * 2000), + y: `-=${14.83 * (abilityDescriptionLineCount - 2)}` + }); + } + }); + // Turn off visibility of passive info by default + this.passiveContainer?.labelImage.setVisible(false); + this.passiveContainer?.nameText?.setVisible(false); + this.passiveContainer?.descriptionText?.setVisible(false); + + const closeFragment = getBBCodeFrag("", TextStyle.WINDOW_ALT); + const rawNature = Utils.toReadableString(Nature[this.pokemon?.getNature()!]); // TODO: is this bang correct? + const nature = `${getBBCodeFrag(Utils.toReadableString(getNatureName(this.pokemon?.getNature()!)), TextStyle.SUMMARY_RED)}${closeFragment}`; // TODO: is this bang correct? + + const memoString = i18next.t("pokemonSummary:memoString", { + metFragment: i18next.t(`pokemonSummary:metFragment.${this.pokemon?.metBiome === -1 ? "apparently" : "normal"}`, { + biome: `${getBBCodeFrag(getBiomeName(this.pokemon?.metBiome!), TextStyle.SUMMARY_RED)}${closeFragment}`, // TODO: is this bang correct? + level: `${getBBCodeFrag(this.pokemon?.metLevel.toString()!, TextStyle.SUMMARY_RED)}${closeFragment}`, // TODO: is this bang correct? + wave: `${getBBCodeFrag((this.pokemon?.metWave ? this.pokemon.metWave.toString()! : i18next.t("pokemonSummary:unknownTrainer")), TextStyle.SUMMARY_RED)}${closeFragment}`, + }), + natureFragment: i18next.t(`pokemonSummary:natureFragment.${rawNature}`, { nature: nature }) + }); + + const memoText = addBBCodeTextObject(this.scene, 7, 113, String(memoString), TextStyle.WINDOW_ALT); + memoText.setOrigin(0, 0); + profileContainer.add(memoText); + break; + case Page.STATS: + const statsContainer = this.scene.add.container(0, -pageBg.height); + pageContainer.add(statsContainer); + + PERMANENT_STATS.forEach((stat, s) => { + const statName = i18next.t(getStatKey(stat)); + const rowIndex = s % 3; + const colIndex = Math.floor(s / 3); + + const natureStatMultiplier = getNatureStatMultiplier(this.pokemon?.getNature()!, s); // TODO: is this bang correct? + + const statLabel = addTextObject(this.scene, 27 + 115 * colIndex + (colIndex === 1 ? 5 : 0), 56 + 16 * rowIndex, statName, natureStatMultiplier === 1 ? TextStyle.SUMMARY : natureStatMultiplier > 1 ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE); + statLabel.setOrigin(0.5, 0); + statsContainer.add(statLabel); + + const statValueText = stat !== Stat.HP + ? Utils.formatStat(this.pokemon?.getStat(stat)!) // TODO: is this bang correct? + : `${Utils.formatStat(this.pokemon?.hp!, true)}/${Utils.formatStat(this.pokemon?.getMaxHp()!, true)}`; // TODO: are those bangs correct? + + const statValue = addTextObject(this.scene, 120 + 88 * colIndex, 56 + 16 * rowIndex, statValueText, TextStyle.WINDOW_ALT); + statValue.setOrigin(1, 0); + statsContainer.add(statValue); + }); + + const itemModifiers = (this.scene.findModifiers(m => m instanceof PokemonHeldItemModifier + && m.pokemonId === this.pokemon?.id, this.playerParty) as PokemonHeldItemModifier[]) + .sort(modifierSortFunc); + + itemModifiers.forEach((item, i) => { + const icon = item.getIcon(this.scene, true); + + icon.setPosition((i % 17) * 12 + 3, 14 * Math.floor(i / 17) + 15); + statsContainer.add(icon); + + icon.setInteractive(new Phaser.Geom.Rectangle(0, 0, 32, 32), Phaser.Geom.Rectangle.Contains); + icon.on("pointerover", () => (this.scene as BattleScene).ui.showTooltip(item.type.name, item.type.getDescription(this.scene), true)); + icon.on("pointerout", () => (this.scene as BattleScene).ui.hideTooltip()); + }); + + const pkmLvl = this.pokemon?.level!; // TODO: is this bang correct? + const pkmLvlExp = this.pokemon?.levelExp!; // TODO: is this bang correct? + const pkmExp = this.pokemon?.exp!; // TODO: is this bang correct? + const pkmSpeciesGrowthRate = this.pokemon?.species.growthRate!; // TODO: is this bang correct? + const relLvExp = getLevelRelExp(pkmLvl + 1, pkmSpeciesGrowthRate); + const expRatio = pkmLvl < this.scene.getMaxExpLevel() ? pkmLvlExp / relLvExp : 0; + + const expLabel = addTextObject(this.scene, 6, 112, i18next.t("pokemonSummary:expPoints"), TextStyle.SUMMARY); + expLabel.setOrigin(0, 0); + statsContainer.add(expLabel); + + const nextLvExpLabel = addTextObject(this.scene, 6, 128, i18next.t("pokemonSummary:nextLv"), TextStyle.SUMMARY); + nextLvExpLabel.setOrigin(0, 0); + statsContainer.add(nextLvExpLabel); + + const expText = addTextObject(this.scene, 208, 112, pkmExp.toString(), TextStyle.WINDOW_ALT); + expText.setOrigin(1, 0); + statsContainer.add(expText); + + const nextLvExp = pkmLvl < this.scene.getMaxExpLevel() + ? getLevelTotalExp(pkmLvl + 1, pkmSpeciesGrowthRate) - pkmExp + : 0; + const nextLvExpText = addTextObject(this.scene, 208, 128, nextLvExp.toString(), TextStyle.WINDOW_ALT); + nextLvExpText.setOrigin(1, 0); + statsContainer.add(nextLvExpText); + + const expOverlay = this.scene.add.image(140, 145, "summary_stats_overlay_exp"); + expOverlay.setOrigin(0, 0); + statsContainer.add(expOverlay); + + const expMaskRect = this.scene.make.graphics({}); + expMaskRect.setScale(6); + expMaskRect.fillStyle(0xFFFFFF); + expMaskRect.beginPath(); + expMaskRect.fillRect(140 + pageContainer.x, 145 + pageContainer.y + 21, Math.floor(expRatio * 64), 3); + + const expMask = expMaskRect.createGeometryMask(); + + expOverlay.setMask(expMask); + break; + case Page.MOVES: + this.movesContainer = this.scene.add.container(5, -pageBg.height + 26); + pageContainer.add(this.movesContainer); + + this.extraMoveRowContainer = this.scene.add.container(0, 64); + this.extraMoveRowContainer.setVisible(false); + this.movesContainer.add(this.extraMoveRowContainer); + + const extraRowOverlay = this.scene.add.image(-2, 1, "summary_moves_overlay_row"); + extraRowOverlay.setOrigin(0, 1); + this.extraMoveRowContainer.add(extraRowOverlay); + + const extraRowText = addTextObject(this.scene, 35, 0, this.summaryUiMode === SummaryUiMode.LEARN_MOVE && this.newMove ? this.newMove.name : i18next.t("pokemonSummary:cancel"), + this.summaryUiMode === SummaryUiMode.LEARN_MOVE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY); + extraRowText.setOrigin(0, 1); + this.extraMoveRowContainer.add(extraRowText); + + if (this.summaryUiMode === SummaryUiMode.LEARN_MOVE) { + this.extraMoveRowContainer.setVisible(true); + + if (this.newMove && this.pokemon) { + const spriteKey = Utils.getLocalizedSpriteKey("types"); + const moveType = this.pokemon.getMoveType(this.newMove); + const newMoveTypeIcon = this.scene.add.sprite(0, 0, spriteKey, Type[moveType].toLowerCase()); + newMoveTypeIcon.setOrigin(0, 1); + this.extraMoveRowContainer.add(newMoveTypeIcon); + } + const ppOverlay = this.scene.add.image(163, -1, "summary_moves_overlay_pp"); + ppOverlay.setOrigin(0, 1); + this.extraMoveRowContainer.add(ppOverlay); + + const pp = Utils.padInt(this.newMove?.pp!, 2, " "); // TODO: is this bang correct? + const ppText = addTextObject(this.scene, 173, 1, `${pp}/${pp}`, TextStyle.WINDOW); + ppText.setOrigin(0, 1); + this.extraMoveRowContainer.add(ppText); + } + + this.moveRowsContainer = this.scene.add.container(0, 0); + this.movesContainer.add(this.moveRowsContainer); + + for (let m = 0; m < 4; m++) { + const move: PokemonMove | null = this.pokemon && this.pokemon.moveset.length > m ? this.pokemon?.moveset[m] : null; + const moveRowContainer = this.scene.add.container(0, 16 * m); + this.moveRowsContainer.add(moveRowContainer); + + if (move && this.pokemon) { + const spriteKey = Utils.getLocalizedSpriteKey("types"); + const moveType = this.pokemon.getMoveType(move.getMove()); + const typeIcon = this.scene.add.sprite(0, 0, spriteKey, Type[moveType].toLowerCase()); + typeIcon.setOrigin(0, 1); + moveRowContainer.add(typeIcon); + } + + const moveText = addTextObject(this.scene, 35, 0, move ? move.getName() : "-", TextStyle.SUMMARY); + moveText.setOrigin(0, 1); + moveRowContainer.add(moveText); + + const ppOverlay = this.scene.add.image(163, -1, "summary_moves_overlay_pp"); + ppOverlay.setOrigin(0, 1); + moveRowContainer.add(ppOverlay); + + const ppText = addTextObject(this.scene, 173, 1, "--/--", TextStyle.WINDOW); + ppText.setOrigin(0, 1); + + if (move) { + const maxPP = move.getMovePp(); + const pp = maxPP - move.ppUsed; + ppText.setText(`${Utils.padInt(pp, 2, " ")}/${Utils.padInt(maxPP, 2, " ")}`); + } + + moveRowContainer.add(ppText); + } + + this.moveDescriptionText = addTextObject(this.scene, 2, 84, "", TextStyle.WINDOW_ALT, { wordWrap: { width: 1212 }}); + this.movesContainer.add(this.moveDescriptionText); + + const moveDescriptionTextMaskRect = this.scene.make.graphics({}); + moveDescriptionTextMaskRect.setScale(6); + moveDescriptionTextMaskRect.fillStyle(0xFFFFFF); + moveDescriptionTextMaskRect.beginPath(); + moveDescriptionTextMaskRect.fillRect(112, 130, 202, 46); + + const moveDescriptionTextMask = moveDescriptionTextMaskRect.createGeometryMask(); + + this.moveDescriptionText.setMask(moveDescriptionTextMask); + break; } } diff --git a/src/ui/target-select-ui-handler.ts b/src/ui/target-select-ui-handler.ts index 3cdda984d3c..4c55a4b960e 100644 --- a/src/ui/target-select-ui-handler.ts +++ b/src/ui/target-select-ui-handler.ts @@ -4,7 +4,7 @@ import { Mode } from "./ui"; import UiHandler from "./ui-handler"; import * as Utils from "../utils"; import { getMoveTargets } from "../data/move"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; import { Moves } from "#enums/moves"; import Pokemon from "#app/field/pokemon"; import { ModifierBar } from "#app/modifier/modifier"; @@ -64,33 +64,33 @@ export default class TargetSelectUiHandler extends UiHandler { let success = false; if (button === Button.ACTION || button === Button.CANCEL) { - const targetIndexes: BattlerIndex[] = this.isMultipleTargets ? this.targets : [this.cursor]; + const targetIndexes: BattlerIndex[] = this.isMultipleTargets ? this.targets : [ this.cursor ]; this.targetSelectCallback(button === Button.ACTION ? targetIndexes : []); success = true; } else if (this.isMultipleTargets) { success = false; } else { switch (button) { - case Button.UP: - if (this.cursor < BattlerIndex.ENEMY && this.targets.findIndex(t => t >= BattlerIndex.ENEMY) > -1) { - success = this.setCursor(this.targets.find(t => t >= BattlerIndex.ENEMY)!); // TODO: is the bang correct here? - } - break; - case Button.DOWN: - if (this.cursor >= BattlerIndex.ENEMY && this.targets.findIndex(t => t < BattlerIndex.ENEMY) > -1) { - success = this.setCursor(this.targets.find(t => t < BattlerIndex.ENEMY)!); // TODO: is the bang correct here? - } - break; - case Button.LEFT: - if (this.cursor % 2 && this.targets.findIndex(t => t === this.cursor - 1) > -1) { - success = this.setCursor(this.cursor - 1); - } - break; - case Button.RIGHT: - if (!(this.cursor % 2) && this.targets.findIndex(t => t === this.cursor + 1) > -1) { - success = this.setCursor(this.cursor + 1); - } - break; + case Button.UP: + if (this.cursor < BattlerIndex.ENEMY && this.targets.findIndex(t => t >= BattlerIndex.ENEMY) > -1) { + success = this.setCursor(this.targets.find(t => t >= BattlerIndex.ENEMY)!); // TODO: is the bang correct here? + } + break; + case Button.DOWN: + if (this.cursor >= BattlerIndex.ENEMY && this.targets.findIndex(t => t < BattlerIndex.ENEMY) > -1) { + success = this.setCursor(this.targets.find(t => t < BattlerIndex.ENEMY)!); // TODO: is the bang correct here? + } + break; + case Button.LEFT: + if (this.cursor % 2 && this.targets.findIndex(t => t === this.cursor - 1) > -1) { + success = this.setCursor(this.cursor - 1); + } + break; + case Button.RIGHT: + if (!(this.cursor % 2) && this.targets.findIndex(t => t === this.cursor + 1) > -1) { + success = this.setCursor(this.cursor + 1); + } + break; } } diff --git a/src/ui/test-dialogue-ui-handler.ts b/src/ui/test-dialogue-ui-handler.ts index 0acd9da193b..34fb80ecc89 100644 --- a/src/ui/test-dialogue-ui-handler.ts +++ b/src/ui/test-dialogue-ui-handler.ts @@ -25,7 +25,7 @@ export default class TestDialogueUiHandler extends FormModalUiHandler { // If the value is an object, execute the same process // si el valor es un objeto ejecuta el mismo proceso - return flattenKeys(value, topKey ?? t, topKey ? midleKey ? [...midleKey, t] : [t] : undefined).filter((t) => t.length > 0); + return flattenKeys(value, topKey ?? t, topKey ? midleKey ? [ ...midleKey, t ] : [ t ] : undefined).filter((t) => t.length > 0); } else if (typeof value === "string" || isNullOrUndefined(value)) { // we check for null or undefined here as per above - the typeof is still an object but the value is null so we need to exit out of this and pass the null key // Return in the format expected by i18next @@ -74,7 +74,7 @@ export default class TestDialogueUiHandler extends FormModalUiHandler { input.setMaxLength(255); input.on("keydown", (inputObject, evt: KeyboardEvent) => { - if (["escape", "space"].some((v) => v === evt.key.toLowerCase() || v === evt.code.toLowerCase()) && ui.getMode() === Mode.AUTO_COMPLETE) { + if ([ "escape", "space" ].some((v) => v === evt.key.toLowerCase() || v === evt.code.toLowerCase()) && ui.getMode() === Mode.AUTO_COMPLETE) { // Delete autocomplete list and recovery focus. inputObject.on("blur", () => inputObject.node.focus(), { once: true }); ui.revertMode(); diff --git a/src/ui/text.ts b/src/ui/text.ts index 58b6343144a..069aa8680fc 100644 --- a/src/ui/text.ts +++ b/src/ui/text.ts @@ -129,84 +129,84 @@ export function getTextStyleOptions(style: TextStyle, uiTheme: UiTheme, extraSty } switch (style) { - case TextStyle.SUMMARY: - case TextStyle.SUMMARY_ALT: - case TextStyle.SUMMARY_BLUE: - case TextStyle.SUMMARY_RED: - case TextStyle.SUMMARY_PINK: - case TextStyle.SUMMARY_GOLD: - case TextStyle.SUMMARY_GRAY: - case TextStyle.SUMMARY_GREEN: - case TextStyle.WINDOW: - case TextStyle.WINDOW_ALT: - shadowXpos = 3; - shadowYpos = 3; - break; - case TextStyle.STATS_LABEL: - let fontSizeLabel = "96px"; - switch (lang) { - case "de": + case TextStyle.SUMMARY: + case TextStyle.SUMMARY_ALT: + case TextStyle.SUMMARY_BLUE: + case TextStyle.SUMMARY_RED: + case TextStyle.SUMMARY_PINK: + case TextStyle.SUMMARY_GOLD: + case TextStyle.SUMMARY_GRAY: + case TextStyle.SUMMARY_GREEN: + case TextStyle.WINDOW: + case TextStyle.WINDOW_ALT: shadowXpos = 3; shadowYpos = 3; - fontSizeLabel = "80px"; break; - default: - fontSizeLabel = "96px"; + case TextStyle.STATS_LABEL: + let fontSizeLabel = "96px"; + switch (lang) { + case "de": + shadowXpos = 3; + shadowYpos = 3; + fontSizeLabel = "80px"; + break; + default: + fontSizeLabel = "96px"; + break; + } + styleOptions.fontSize = fontSizeLabel; break; - } - styleOptions.fontSize = fontSizeLabel; - break; - case TextStyle.STATS_VALUE: - shadowXpos = 3; - shadowYpos = 3; - let fontSizeValue = "96px"; - switch (lang) { - case "de": - fontSizeValue = "80px"; + case TextStyle.STATS_VALUE: + shadowXpos = 3; + shadowYpos = 3; + let fontSizeValue = "96px"; + switch (lang) { + case "de": + fontSizeValue = "80px"; + break; + default: + fontSizeValue = "96px"; + break; + } + styleOptions.fontSize = fontSizeValue; break; - default: - fontSizeValue = "96px"; + case TextStyle.MESSAGE: + case TextStyle.SETTINGS_LABEL: + case TextStyle.SETTINGS_LOCKED: + case TextStyle.SETTINGS_SELECTED: + break; + case TextStyle.BATTLE_INFO: + case TextStyle.MONEY: + case TextStyle.TOOLTIP_TITLE: + styleOptions.fontSize = defaultFontSize - 24; + shadowXpos = 3.5; + shadowYpos = 3.5; + break; + case TextStyle.PARTY: + case TextStyle.PARTY_RED: + styleOptions.fontSize = defaultFontSize - 30; + styleOptions.fontFamily = "pkmnems"; + break; + case TextStyle.TOOLTIP_CONTENT: + styleOptions.fontSize = defaultFontSize - 32; + shadowXpos = 3; + shadowYpos = 3; + break; + case TextStyle.MOVE_INFO_CONTENT: + styleOptions.fontSize = defaultFontSize - 40; + shadowXpos = 3; + shadowYpos = 3; + break; + case TextStyle.SMALLER_WINDOW_ALT: + styleOptions.fontSize = defaultFontSize - 36; + shadowXpos = 3; + shadowYpos = 3; + break; + case TextStyle.BGM_BAR: + styleOptions.fontSize = defaultFontSize - 24; + shadowXpos = 3; + shadowYpos = 3; break; - } - styleOptions.fontSize = fontSizeValue; - break; - case TextStyle.MESSAGE: - case TextStyle.SETTINGS_LABEL: - case TextStyle.SETTINGS_LOCKED: - case TextStyle.SETTINGS_SELECTED: - break; - case TextStyle.BATTLE_INFO: - case TextStyle.MONEY: - case TextStyle.TOOLTIP_TITLE: - styleOptions.fontSize = defaultFontSize - 24; - shadowXpos = 3.5; - shadowYpos = 3.5; - break; - case TextStyle.PARTY: - case TextStyle.PARTY_RED: - styleOptions.fontSize = defaultFontSize - 30; - styleOptions.fontFamily = "pkmnems"; - break; - case TextStyle.TOOLTIP_CONTENT: - styleOptions.fontSize = defaultFontSize - 32; - shadowXpos = 3; - shadowYpos = 3; - break; - case TextStyle.MOVE_INFO_CONTENT: - styleOptions.fontSize = defaultFontSize - 40; - shadowXpos = 3; - shadowYpos = 3; - break; - case TextStyle.SMALLER_WINDOW_ALT: - styleOptions.fontSize = defaultFontSize - 36; - shadowXpos = 3; - shadowYpos = 3; - break; - case TextStyle.BGM_BAR: - styleOptions.fontSize = defaultFontSize - 24; - shadowXpos = 3; - shadowYpos = 3; - break; } const shadowColor = getTextColor(style, true, uiTheme); @@ -243,7 +243,7 @@ export function getBBCodeFrag(content: string, textStyle: TextStyle, uiTheme: Ui export function getTextWithColors(content: string, primaryStyle: TextStyle, uiTheme: UiTheme = UiTheme.DEFAULT): string { // Apply primary styling before anything else let text = getBBCodeFrag(content, primaryStyle, uiTheme) + "[/color][/shadow]"; - const primaryStyleString = [...text.match(new RegExp(/\[color=[^\[]*\]\[shadow=[^\[]*\]/i))!][0]; + const primaryStyleString = [ ...text.match(new RegExp(/\[color=[^\[]*\]\[shadow=[^\[]*\]/i))! ][0]; // Set custom colors text = text.replace(/@\[([^{]*)\]{([^}]*)}/gi, (substring, textStyle: string, textToColor: string) => { @@ -257,110 +257,110 @@ export function getTextWithColors(content: string, primaryStyle: TextStyle, uiTh export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: UiTheme = UiTheme.DEFAULT): string { const isLegacyTheme = uiTheme === UiTheme.LEGACY; switch (textStyle) { - case TextStyle.MESSAGE: - return !shadow ? "#f8f8f8" : "#6b5a73"; - case TextStyle.WINDOW: - case TextStyle.MOVE_INFO_CONTENT: - case TextStyle.MOVE_PP_FULL: - case TextStyle.TOOLTIP_CONTENT: - case TextStyle.SETTINGS_VALUE: - if (isLegacyTheme) { + case TextStyle.MESSAGE: + return !shadow ? "#f8f8f8" : "#6b5a73"; + case TextStyle.WINDOW: + case TextStyle.MOVE_INFO_CONTENT: + case TextStyle.MOVE_PP_FULL: + case TextStyle.TOOLTIP_CONTENT: + case TextStyle.SETTINGS_VALUE: + if (isLegacyTheme) { + return !shadow ? "#484848" : "#d0d0c8"; + } + return !shadow ? "#f8f8f8" : "#6b5a73"; + case TextStyle.MOVE_PP_HALF_FULL: + if (isLegacyTheme) { + return !shadow ? "#a68e17" : "#ebd773"; + } + return !shadow ? "#ccbe00" : "#6e672c"; + case TextStyle.MOVE_PP_NEAR_EMPTY: + if (isLegacyTheme) { + return !shadow ? "#d64b00" : "#f7b18b"; + } + return !shadow ? "#d64b00" : "#69402a"; + case TextStyle.MOVE_PP_EMPTY: + if (isLegacyTheme) { + return !shadow ? "#e13d3d" : "#fca2a2"; + } + return !shadow ? "#e13d3d" : "#632929"; + case TextStyle.WINDOW_ALT: return !shadow ? "#484848" : "#d0d0c8"; - } - return !shadow ? "#f8f8f8" : "#6b5a73"; - case TextStyle.MOVE_PP_HALF_FULL: - if (isLegacyTheme) { - return !shadow ? "#a68e17" : "#ebd773"; - } - return !shadow ? "#ccbe00" : "#6e672c"; - case TextStyle.MOVE_PP_NEAR_EMPTY: - if (isLegacyTheme) { - return !shadow ? "#d64b00" : "#f7b18b"; - } - return !shadow ? "#d64b00" : "#69402a"; - case TextStyle.MOVE_PP_EMPTY: - if (isLegacyTheme) { - return !shadow ? "#e13d3d" : "#fca2a2"; - } - return !shadow ? "#e13d3d" : "#632929"; - case TextStyle.WINDOW_ALT: - return !shadow ? "#484848" : "#d0d0c8"; - case TextStyle.BATTLE_INFO: - if (isLegacyTheme) { - return !shadow ? "#404040" : "#ded6b5"; - } - return !shadow ? "#f8f8f8" : "#6b5a73"; - case TextStyle.PARTY: - return !shadow ? "#f8f8f8" : "#707070"; - case TextStyle.PARTY_RED: - return !shadow ? "#f89890" : "#984038"; - case TextStyle.SUMMARY: - return !shadow ? "#f8f8f8" : "#636363"; - case TextStyle.SUMMARY_ALT: - if (isLegacyTheme) { + case TextStyle.BATTLE_INFO: + if (isLegacyTheme) { + return !shadow ? "#404040" : "#ded6b5"; + } + return !shadow ? "#f8f8f8" : "#6b5a73"; + case TextStyle.PARTY: + return !shadow ? "#f8f8f8" : "#707070"; + case TextStyle.PARTY_RED: + return !shadow ? "#f89890" : "#984038"; + case TextStyle.SUMMARY: return !shadow ? "#f8f8f8" : "#636363"; - } - return !shadow ? "#484848" : "#d0d0c8"; - case TextStyle.SUMMARY_RED: - case TextStyle.TOOLTIP_TITLE: - return !shadow ? "#e70808" : "#ffbd73"; - case TextStyle.SUMMARY_BLUE: - return !shadow ? "#40c8f8" : "#006090"; - case TextStyle.SUMMARY_PINK: - return !shadow ? "#f89890" : "#984038"; - case TextStyle.SUMMARY_GOLD: - case TextStyle.MONEY: - return !shadow ? "#e8e8a8" : "#a0a060"; - case TextStyle.SETTINGS_LOCKED: - case TextStyle.SUMMARY_GRAY: - return !shadow ? "#a0a0a0" : "#636363"; - case TextStyle.STATS_LABEL: - return !shadow ? "#f8b050" : "#c07800"; - case TextStyle.STATS_VALUE: - if (isLegacyTheme) { + case TextStyle.SUMMARY_ALT: + if (isLegacyTheme) { + return !shadow ? "#f8f8f8" : "#636363"; + } return !shadow ? "#484848" : "#d0d0c8"; - } - return !shadow ? "#f8f8f8" : "#6b5a73"; - case TextStyle.SUMMARY_GREEN: - return !shadow ? "#78c850" : "#306850"; - case TextStyle.SETTINGS_LABEL: - case TextStyle.PERFECT_IV: - return !shadow ? "#f8b050" : "#c07800"; - case TextStyle.SETTINGS_SELECTED: - return !shadow ? "#f88880" : "#f83018"; - case TextStyle.SMALLER_WINDOW_ALT: - return !shadow ? "#484848" : "#d0d0c8"; - case TextStyle.BGM_BAR: - return !shadow ? "#f8f8f8" : "#6b5a73"; + case TextStyle.SUMMARY_RED: + case TextStyle.TOOLTIP_TITLE: + return !shadow ? "#e70808" : "#ffbd73"; + case TextStyle.SUMMARY_BLUE: + return !shadow ? "#40c8f8" : "#006090"; + case TextStyle.SUMMARY_PINK: + return !shadow ? "#f89890" : "#984038"; + case TextStyle.SUMMARY_GOLD: + case TextStyle.MONEY: + return !shadow ? "#e8e8a8" : "#a0a060"; + case TextStyle.SETTINGS_LOCKED: + case TextStyle.SUMMARY_GRAY: + return !shadow ? "#a0a0a0" : "#636363"; + case TextStyle.STATS_LABEL: + return !shadow ? "#f8b050" : "#c07800"; + case TextStyle.STATS_VALUE: + if (isLegacyTheme) { + return !shadow ? "#484848" : "#d0d0c8"; + } + return !shadow ? "#f8f8f8" : "#6b5a73"; + case TextStyle.SUMMARY_GREEN: + return !shadow ? "#78c850" : "#306850"; + case TextStyle.SETTINGS_LABEL: + case TextStyle.PERFECT_IV: + return !shadow ? "#f8b050" : "#c07800"; + case TextStyle.SETTINGS_SELECTED: + return !shadow ? "#f88880" : "#f83018"; + case TextStyle.SMALLER_WINDOW_ALT: + return !shadow ? "#484848" : "#d0d0c8"; + case TextStyle.BGM_BAR: + return !shadow ? "#f8f8f8" : "#6b5a73"; } } export function getModifierTierTextTint(tier: ModifierTier): integer { switch (tier) { - case ModifierTier.COMMON: - return 0xf8f8f8; - case ModifierTier.GREAT: - return 0x4998f8; - case ModifierTier.ULTRA: - return 0xf8d038; - case ModifierTier.ROGUE: - return 0xdb4343; - case ModifierTier.MASTER: - return 0xe331c5; - case ModifierTier.LUXURY: - return 0xe74c18; + case ModifierTier.COMMON: + return 0xf8f8f8; + case ModifierTier.GREAT: + return 0x4998f8; + case ModifierTier.ULTRA: + return 0xf8d038; + case ModifierTier.ROGUE: + return 0xdb4343; + case ModifierTier.MASTER: + return 0xe331c5; + case ModifierTier.LUXURY: + return 0xe74c18; } } export function getEggTierTextTint(tier: EggTier): integer { switch (tier) { - case EggTier.COMMON: - return getModifierTierTextTint(ModifierTier.COMMON); - case EggTier.GREAT: - return getModifierTierTextTint(ModifierTier.GREAT); - case EggTier.ULTRA: - return getModifierTierTextTint(ModifierTier.ULTRA); - case EggTier.MASTER: - return getModifierTierTextTint(ModifierTier.MASTER); + case EggTier.COMMON: + return getModifierTierTextTint(ModifierTier.COMMON); + case EggTier.RARE: + return getModifierTierTextTint(ModifierTier.GREAT); + case EggTier.EPIC: + return getModifierTierTextTint(ModifierTier.ULTRA); + case EggTier.LEGENDARY: + return getModifierTierTextTint(ModifierTier.MASTER); } } diff --git a/src/ui/time-of-day-widget.ts b/src/ui/time-of-day-widget.ts index ea80a6e524a..66fe5cc9ac3 100644 --- a/src/ui/time-of-day-widget.ts +++ b/src/ui/time-of-day-widget.ts @@ -21,9 +21,9 @@ export default class TimeOfDayWidget extends Phaser.GameObjects.Container { /** A map containing all timeOfDayIcon arrays with a matching string key for easier iteration */ private timeOfDayIconPairs: Map = new Map([ - ["bg", this.timeOfDayIconBgs], - ["mg", this.timeOfDayIconMgs], - ["fg", this.timeOfDayIconFgs],]); + [ "bg", this.timeOfDayIconBgs ], + [ "mg", this.timeOfDayIconMgs ], + [ "fg", this.timeOfDayIconFgs ],]); /** The current time of day */ private currentTime: TimeOfDay = TimeOfDay.ALL; @@ -66,7 +66,7 @@ export default class TimeOfDayWidget extends Phaser.GameObjects.Container { } }); // Store a flat array of all icons for later - this.timeOfDayIcons = [this.timeOfDayIconBgs, this.timeOfDayIconMgs, this.timeOfDayIconFgs].flat(); + this.timeOfDayIcons = [ this.timeOfDayIconBgs, this.timeOfDayIconMgs, this.timeOfDayIconFgs ].flat(); this.add(this.timeOfDayIcons); this.battleScene.eventTarget.addEventListener(BattleSceneEventType.ENCOUNTER_PHASE, this.onEncounterPhaseEvent); @@ -78,21 +78,21 @@ export default class TimeOfDayWidget extends Phaser.GameObjects.Container { */ private getBackTween(): Phaser.Types.Tweens.TweenBuilderConfig[] { const rotate = { - targets: [this.timeOfDayIconMgs[0], this.timeOfDayIconMgs[1]], + targets: [ this.timeOfDayIconMgs[0], this.timeOfDayIconMgs[1] ], angle: "+=90", duration: Utils.fixedInt(1500), ease: "Back.easeOut", paused: !this.parentVisible, }; const fade = { - targets: [this.timeOfDayIconBgs[1], this.timeOfDayIconMgs[1], this.timeOfDayIconFgs[1]], + targets: [ this.timeOfDayIconBgs[1], this.timeOfDayIconMgs[1], this.timeOfDayIconFgs[1] ], alpha: 0, duration: Utils.fixedInt(500), ease: "Linear", paused: !this.parentVisible, }; - return [rotate, fade]; + return [ rotate, fade ]; } /** @@ -101,21 +101,21 @@ export default class TimeOfDayWidget extends Phaser.GameObjects.Container { */ private getBounceTween(): Phaser.Types.Tweens.TweenBuilderConfig[] { const bounce = { - targets: [this.timeOfDayIconMgs[0], this.timeOfDayIconMgs[1]], + targets: [ this.timeOfDayIconMgs[0], this.timeOfDayIconMgs[1] ], angle: "+=90", duration: Utils.fixedInt(2000), ease: "Bounce.easeOut", paused: !this.parentVisible, }; const fade = { - targets: [this.timeOfDayIconBgs[1], this.timeOfDayIconMgs[1], this.timeOfDayIconFgs[1]], + targets: [ this.timeOfDayIconBgs[1], this.timeOfDayIconMgs[1], this.timeOfDayIconFgs[1] ], alpha: 0, duration: Utils.fixedInt(800), ease: "Linear", paused: !this.parentVisible, }; - return [bounce, fade]; + return [ bounce, fade ]; } /** Resets all icons to the proper depth, texture, and alpha so they are ready to tween */ @@ -129,7 +129,7 @@ export default class TimeOfDayWidget extends Phaser.GameObjects.Container { icons[0].setTexture(TimeOfDay[this.currentTime].toLowerCase() + "_icon_" + key); icons[1].setTexture(TimeOfDay[this.previousTime].toLowerCase() + "_icon_" + key); }); - this.timeOfDayIconMgs[0].setRotation(-90 * (3.14/180)); + this.timeOfDayIconMgs[0].setRotation(-90 * (3.14 / 180)); this.timeOfDayIcons.forEach(icon => icon.setAlpha(1)); } diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index 79baf407fb6..f7972af2cc2 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -98,7 +98,7 @@ export default class TitleUiHandler extends OptionSelectUiHandler { this.splashMessage = Utils.randItem(getSplashMessages()); this.splashMessageText.setText(i18next.t(this.splashMessage, { count: TitleUiHandler.BATTLES_WON_FALLBACK })); - this.appVersionText.setText("v"+version); + this.appVersionText.setText("v" + version); const ui = this.getUi(); diff --git a/src/ui/ui-handler.ts b/src/ui/ui-handler.ts index d9f0a876b71..bb7b1e038db 100644 --- a/src/ui/ui-handler.ts +++ b/src/ui/ui-handler.ts @@ -1,7 +1,7 @@ import BattleScene from "../battle-scene"; import { TextStyle, getTextColor } from "./text"; import { Mode } from "./ui"; -import {Button} from "#enums/buttons"; +import { Button } from "#enums/buttons"; /** * A basic abstract class to act as a holder and processor for UI elements. diff --git a/src/ui/ui-theme.ts b/src/ui/ui-theme.ts index 75725910b82..89c56384bd0 100644 --- a/src/ui/ui-theme.ts +++ b/src/ui/ui-theme.ts @@ -10,12 +10,12 @@ export enum WindowVariant { export function getWindowVariantSuffix(windowVariant: WindowVariant): string { switch (windowVariant) { - case WindowVariant.THIN: - return "_thin"; - case WindowVariant.XTHIN: - return "_xthin"; - default: - return ""; + case WindowVariant.THIN: + return "_thin"; + case WindowVariant.XTHIN: + return "_xthin"; + default: + return ""; } } @@ -55,8 +55,8 @@ export function addWindow(scene: BattleScene, x: number, y: number, width: numbe */ const maskRect = new Phaser.GameObjects.Rectangle( scene, - 6*(x - (mergeMaskLeft ? 2 : 0) - (maskOffsetX || 0)), - 6*(y + (mergeMaskTop ? 2 : 0) + (maskOffsetY || 0)), + 6 * (x - (mergeMaskLeft ? 2 : 0) - (maskOffsetX || 0)), + 6 * (y + (mergeMaskTop ? 2 : 0) + (maskOffsetY || 0)), width - (mergeMaskLeft ? 2 : 0), height - (mergeMaskTop ? 2 : 0), 0xffffff diff --git a/src/ui/ui.ts b/src/ui/ui.ts index 7e00c87cc5f..63cd48ab1cd 100644 --- a/src/ui/ui.ts +++ b/src/ui/ui.ts @@ -34,7 +34,6 @@ import SaveSlotSelectUiHandler from "./save-slot-select-ui-handler"; import TitleUiHandler from "./title-ui-handler"; import SavingIconHandler from "./saving-icon-handler"; import UnavailableModalUiHandler from "./unavailable-modal-ui-handler"; -import OutdatedModalUiHandler from "./outdated-modal-ui-handler"; import SessionReloadModalUiHandler from "./session-reload-modal-ui-handler"; import { Button } from "#enums/buttons"; import i18next from "i18next"; @@ -90,7 +89,6 @@ export enum Mode { LOADING, SESSION_RELOAD, UNAVAILABLE, - OUTDATED, CHALLENGE_SELECT, RENAME_POKEMON, RUN_HISTORY, @@ -134,7 +132,6 @@ const noTransitionModes = [ Mode.LOADING, Mode.SESSION_RELOAD, Mode.UNAVAILABLE, - Mode.OUTDATED, Mode.RENAME_POKEMON, Mode.TEST_DIALOGUE, Mode.AUTO_COMPLETE, @@ -200,7 +197,6 @@ export default class UI extends Phaser.GameObjects.Container { new LoadingModalUiHandler(scene), new SessionReloadModalUiHandler(scene), new UnavailableModalUiHandler(scene), - new OutdatedModalUiHandler(scene), new GameChallengesUiHandler(scene), new RenameFormUiHandler(scene), new RunHistoryUiHandler(scene), @@ -273,7 +269,7 @@ export default class UI extends Phaser.GameObjects.Container { } const battleScene = this.scene as BattleScene; - if ([Mode.CONFIRM, Mode.COMMAND, Mode.FIGHT, Mode.MESSAGE].includes(this.mode)) { + if ([ Mode.CONFIRM, Mode.COMMAND, Mode.FIGHT, Mode.MESSAGE ].includes(this.mode)) { battleScene?.processInfoButton(pressed); return true; } diff --git a/src/ui/unavailable-modal-ui-handler.ts b/src/ui/unavailable-modal-ui-handler.ts index 3375fb930e6..92b1c2f1b4e 100644 --- a/src/ui/unavailable-modal-ui-handler.ts +++ b/src/ui/unavailable-modal-ui-handler.ts @@ -52,7 +52,7 @@ export default class UnavailableModalUiHandler extends ModalUiHandler { tryReconnect(): void { updateUserInfo().then(response => { - if (response[0] || [200, 400].includes(response[1])) { + if (response[0] || [ 200, 400 ].includes(response[1])) { this.reconnectTimer = null; this.reconnectDuration = this.minTime; this.scene.playSound("se/pb_bounce_1"); diff --git a/src/utils.test.ts b/src/utils.test.ts index 93f2a96ec4c..3f5b835b03b 100644 --- a/src/utils.test.ts +++ b/src/utils.test.ts @@ -1,4 +1,4 @@ -import {expect, describe, it, beforeAll} from "vitest"; +import { expect, describe, it, beforeAll } from "vitest"; import { randomString, padInt } from "./utils"; import Phaser from "phaser"; diff --git a/src/utils.ts b/src/utils.ts index 7a0def1a950..8a35a4b3f07 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -38,10 +38,6 @@ export function shiftCharCodes(str: string, shiftCount: integer) { return newStr; } -export function clampInt(value: integer, min: integer, max: integer): integer { - return Math.min(Math.max(value, min), max); -} - export function randGauss(stdev: number, mean: number = 0): number { if (!stdev) { return 0; @@ -149,7 +145,7 @@ export function randSeedShuffle(items: T[]): T[] { const newArray = items.slice(0); for (let i = items.length - 1; i > 0; i--) { const j = Phaser.Math.RND.integerInRange(0, i); - [newArray[i], newArray[j]] = [newArray[j], newArray[i]]; + [ newArray[i], newArray[j] ] = [ newArray[j], newArray[i] ]; } return newArray; } @@ -198,23 +194,23 @@ export function formatLargeNumber(count: integer, threshold: integer): string { const ret = count.toString(); let suffix = ""; switch (Math.ceil(ret.length / 3) - 1) { - case 1: - suffix = "K"; - break; - case 2: - suffix = "M"; - break; - case 3: - suffix = "B"; - break; - case 4: - suffix = "T"; - break; - case 5: - suffix = "q"; - break; - default: - return "?"; + case 1: + suffix = "K"; + break; + case 2: + suffix = "M"; + break; + case 3: + suffix = "B"; + break; + case 4: + suffix = "T"; + break; + case 5: + suffix = "q"; + break; + default: + return "?"; } const digits = ((ret.length + 2) % 3) + 1; let decimalNumber = ret.slice(digits, digits + 2); @@ -225,7 +221,7 @@ export function formatLargeNumber(count: integer, threshold: integer): string { } // Abbreviations from 10^0 to 10^33 -const AbbreviationsLargeNumber: string[] = ["", "K", "M", "B", "t", "q", "Q", "s", "S", "o", "n", "d"]; +const AbbreviationsLargeNumber: string[] = [ "", "K", "M", "B", "t", "q", "Q", "s", "S", "o", "n", "d" ]; export function formatFancyLargeNumber(number: number, rounded: number = 3): string { let exponent: number; @@ -274,7 +270,7 @@ export const isLocal = ( /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/.test(window.location.hostname)) && window.location.port !== "") || window.location.hostname === ""; -export const localServerUrl = import.meta.env.VITE_SERVER_URL ?? `http://${window.location.hostname}:${window.location.port+1}`; +export const localServerUrl = import.meta.env.VITE_SERVER_URL ?? `http://${window.location.hostname}:${window.location.port + 1}`; // Set the server URL based on whether it's local or not export const apiUrl = localServerUrl ?? "https://api.pokerogue.net"; @@ -425,7 +421,7 @@ export function rgbToHsv(r: integer, g: integer, b: integer) { const v = Math.max(r, g, b); const c = v - Math.min(r, g, b); const h = c && ((v === r) ? (g - b) / c : ((v === g) ? 2 + (b - r) / c : 4 + (r - g) / c)); - return [ 60 * (h < 0 ? h + 6 : h), v && c / v, v]; + return [ 60 * (h < 0 ? h + 6 : h), v && c / v, v ]; } /** @@ -445,7 +441,7 @@ export function deltaRgb(rgb1: integer[], rgb2: integer[]): integer { } export function rgbHexToRgba(hex: string) { - const color = hex.match(/^([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i) ?? ["000000", "00", "00", "00"]; + const color = hex.match(/^([\da-f]{2})([\da-f]{2})([\da-f]{2})$/i) ?? [ "000000", "00", "00", "00" ]; return { r: parseInt(color[1], 16), g: parseInt(color[2], 16), @@ -491,18 +487,18 @@ export function verifyLang(lang?: string): boolean { } switch (lang) { - case "es": - case "fr": - case "de": - case "it": - case "zh-CN": - case "zh-TW": - case "pt-BR": - case "ko": - case "ja": - return true; - default: - return false; + case "es": + case "fr": + case "de": + case "it": + case "zh-CN": + case "zh-TW": + case "pt-BR": + case "ko": + case "ja": + return true; + default: + return false; } } @@ -512,7 +508,7 @@ export function verifyLang(lang?: string): boolean { */ export function printContainerList(container: Phaser.GameObjects.Container): void { console.log(container.list.map(go => { - return {type: go.type, name: go.name}; + return { type: go.type, name: go.name }; })); }