diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000000..e94afd0a9be --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,61 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node +{ + "name": "Node.js & TypeScript", + // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile + "image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm", + "features": { + "ghcr.io/devcontainers/features/github-cli:1": { + "installDirectlyFromGitHubRelease": true, + "version": "latest" + }, + "ghcr.io/devcontainers-extra/features/pnpm:2": { + "version": "latest" + } + }, + "customizations": { + "vscode": { + "settings": { + // # Formatter configs + "editor.defaultFormatter": "biomejs.biome", + "editor.tabSize": 2, + "editor.insertSpaces": true, + "editor.codeActionsOnSave": { + "source.addMissingImports.ts": "always", + "source.removeUnusedImports": "always", + "source.fixAll.biome": "always", + "source.organizeImports.biome": "always" + }, + "biome.suggestInstallingGlobally": false, + + // # JS/TS setting overrides + "javascript.preferences.importModuleSpecifier": "non-relative", + "javascript.preferences.importModuleSpecifierEnding": "index", + "javascript.preferGoToSourceDefinition": true, + "javascript.updateImportsOnFileMove.enabled": "always", + + "typescript.preferences.importModuleSpecifier": "non-relative", + "typescript.preferences.importModuleSpecifierEnding": "index", + "typescript.preferGoToSourceDefinition": true, + "typescript.updateImportsOnFileMove.enabled": "always", + + "typescript.tsserver.experimental.enableProjectDiagnostics": true, + + // # Miscellaneous + "npm.packageManager": "pnpm", + "npm.scriptRunner": "pnpm", + "vitest.cliArguments": "--no-isolate" + }, + "extensions": [ + "biomejs.biome", + "YoavBls.pretty-ts-errors", + "vitest.explorer", + "adpyke.codesnap", // Bind to a hotkey (ctrl+\, etc) for best results + "aaron-bond.better-comments", + "MuTsunTsai.jsdoc-link" + ] + } + }, + "postCreateCommand": "pnpm install", + "forwardPorts": [8000] +} diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 35a31f6b4d1..b1543b2cb44 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -36,12 +36,18 @@ jobs: exit 1 fi shell: bash + - uses: actions/create-github-app-token@v2 + id: app-token + with: + app-id: ${{ secrets.PAGEFAULT_APP_ID }} + private-key: ${{ secrets.PAGEFAULT_APP_PRIVATE_KEY }} - name: Check out code uses: actions/checkout@v4 with: submodules: "recursive" # Always base off of beta branch, regardless of the branch the workflow was triggered from. ref: beta + token: ${{ steps.app-token.outputs.token }} - name: Create release branch run: git checkout -b release # In order to be able to open a PR into beta, we need the branch to have at least one change. @@ -56,7 +62,7 @@ jobs: run: git push origin release # The repository variable is used by the deploy-beta workflow to determine whether to deploy from beta or release. - name: Set repository variable - run: GITHUB_TOKEN="${{ secrets.RW_VARS_PAT }}" gh variable set BETA_DEPLOY_BRANCH --body "release" + run: GITHUB_TOKEN="${{ steps.app-token.outputs.token }}" gh variable set BETA_DEPLOY_BRANCH --body "release" - name: Create pull request to main run: | gh pr create --base main \ diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index 1588a15afeb..84d5964064f 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -5,10 +5,12 @@ on: branches: - main - beta + - release pull_request: branches: - main - beta + - release merge_group: types: [checks_requested] diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 82f5abd23a1..a5e8f96961e 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -5,10 +5,12 @@ on: branches: - main - beta + - release pull_request: branches: - main - beta + - release merge_group: types: [checks_requested] diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 764a35ace60..2b9f6dc9c0d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -5,10 +5,12 @@ on: branches: - main - beta + - release pull_request: branches: - main - beta + - release merge_group: types: [checks_requested] workflow_dispatch: diff --git a/.gitignore b/.gitignore index 00df0002e01..299767e742a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,9 +12,10 @@ dist dist-ssr *.local -# Editor directories and files -.vscode +# Editor directories and files (excluding `extensions.json` for devcontainer) *.code-workspace +.vscode/* +!.vscode/extensions.json .idea .DS_Store *.suo diff --git a/.ls-lint.yml b/.ls-lint.yml index 22f08f72938..0086367367b 100644 --- a/.ls-lint.yml +++ b/.ls-lint.yml @@ -26,3 +26,4 @@ ignore: - .git - public - dist + - .devcontainer diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000000..81abc8df2c0 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,13 @@ +{ + "recommendations": [ + "biomejs.biome", + "YoavBls.pretty-ts-errors", + "vitest.explorer", + + // This stuff isn't mandatory - it's just nice to have :) + + "adpyke.codesnap", // Bind to a hotkey (ctrl+\, etc) for best results + "aaron-bond.better-comments", + "MuTsunTsai.jsdoc-link" + ] +} \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0217ebd28a6..04ab7ff4faa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Thank you for taking the time to contribute, every little bit helps. This project is entirely open-source and unmonetized - community contributions are what keep it alive! -Please make sure you understand everything relevant to your changes from the [Table of Contents](#-table-of-contents), and absolutely *feel free to reach out in the **#dev-corner** channel on [Discord](https://discord.gg/pokerogue)*. +Please make sure you understand everything relevant to your changes from the [Table of Contents](#-table-of-contents), and absolutely *feel free to reach out in the **#dev-corner** channel on [Discord](https://discord.gg/pokerogue)*. We are here to help and the better you understand what you're working on, the easier it will be for it to find its way into the game. ## 📄 Table of Contents @@ -16,19 +16,36 @@ We are here to help and the better you understand what you're working on, the ea ## 🛠️ Development Basics -PokéRogue is built with [Typescript](https://www.typescriptlang.org/docs/handbook/intro.html), using the [Phaser](https://github.com/phaserjs/phaser) game framework. +PokéRogue is built with [Typescript](https://www.typescriptlang.org/docs/handbook/intro.html), using the [Phaser](https://github.com/phaserjs/phaser) game framework. -If you have the motivation and experience with Typescript/Javascript (or are willing to learn) you can contribute by forking the repository and making pull requests with contributions. +If you have the motivation and experience with Typescript/Javascript (or are willing to learn), you can contribute by forking the repository and making pull requests with contributions. ## 💻 Environment Setup -### Prerequisites +### Codespaces/Devcontainer Environment -- node: >=22.14.0 - [manage with pnpm](https://pnpm.io/cli/env) | [manage with fnm](https://github.com/Schniz/fnm) | [manage with nvm](https://github.com/nvm-sh/nvm) +Arguably the easiest way to get started is by using the prepared development environment. + +We have a `.devcontainer/devcontainer.json` file, meaning we are compatible with: + +- [![Open in GitHub Codespaces][codespaces-badge]][codespaces-link], or +- the [Visual Studio Code Remote - Containers][devcontainer-ext] extension. + +This Linux environment comes with all required dependencies needed to start working on the project. + +[codespaces-badge]: +[codespaces-link]: +[devcontainer-ext]: + +### Local Development + +#### Prerequisites + +- node: >=22.14.0 - [manage with pnpm](https://pnpm.io/cli/env) | [manage with fnm](https://github.com/Schniz/fnm) | [manage with nvm](https://github.com/nvm-sh/nvm) | [manage with volta.sh](https://volta.sh/) - pnpm: 10.x - [how to install](https://pnpm.io/installation) (not recommended to install via `npm` on Windows native) | [alternate method - volta.sh](https://volta.sh/) - The repository [forked](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) and [cloned](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) locally on your device -### Running Locally +#### Running Locally 1. Run `pnpm install` from the repository root - *if you run into any errors, reach out in the **#dev-corner** channel on Discord* @@ -36,7 +53,7 @@ If you have the motivation and experience with Typescript/Javascript (or are wil ## 🚀 Getting Started -A great way to develop an understanding of how the project works is to look at test cases (located in [the `test` folder](./test/)). +A great way to develop an understanding of how the project works is to look at test cases (located in [the `test` folder](./test/)). Tests show you both how things are supposed to work and the expected "flow" to get from point A to point B in battles. *This is a big project and you will be confused at times - never be afraid to reach out and ask questions in **#dev-corner***! @@ -50,7 +67,7 @@ Most issues are bugs and are labeled with their area, such as `Move`, `Ability`, - `P2`: Minor - Incorrect (but non-crashing) move/ability/interaction - `P3`: No gameplay impact - typo, minor graphical error, etc. -Also under issues, you can take a look at the [List of Partial / Unimplemented Moves and Abilities](https://github.com/pagefaultgames/pokerogue/issues/3503) and the [Bug Board](https://github.com/orgs/pagefaultgames/projects/3) (the latter is essentially the same as the issues page but easier to work with). +Also under issues, you can take a look at the [List of Partial / Unimplemented Moves and Abilities](https://github.com/pagefaultgames/pokerogue/issues/3503) and the [Bug Board](https://github.com/orgs/pagefaultgames/projects/3). The latter is essentially the same as the issues page, so take your pick. You are free to comment on any issue so that you may be assigned to it and we can avoid multiple people working on the same thing. @@ -58,7 +75,7 @@ You are free to comment on any issue so that you may be assigned to it and we ca You can find the auto-generated documentation [here](https://pagefaultgames.github.io/pokerogue/main/index.html). -Additionally, the [docs folder](./docs) contains a variety of in-depth documents and guides useful for aspiring contributors. +Additionally, the [docs folder](./docs) contains a variety of in-depth documents and guides useful for aspiring contributors. \ Notable topics include: - [Commenting your code](./docs/comments.md) - [Linting & Formatting](./docs/linting.md) @@ -86,17 +103,17 @@ const overrides = { ``` Read through `src/overrides.ts` file to find the override that fits your needs - there are a lot of them! -If the situation you're trying to test can't be created using existing overrides (or with the [Dev Save](#-development-save-file)), reach out in **#dev-corner**. +If the situation you're trying to test can't be created using existing overrides (or with the [Dev Save](#-development-save-file)), reach out in **#dev-corner**. You can get help testing your specific changes, and you might have found a new override that needs to be created! ### 2 - Automatic Testing > PokéRogue uses [Vitest](https://vitest.dev/) for automatic testing. Checking out the existing tests in the [test](./test/) folder is a great way to understand how this works, and to get familiar with the project as a whole. -To make sure your changes didn't break any existing test cases, run `pnpm test:silent` in your terminal. You can also provide an argument to the command: to run only the Dancer (ability) tests, you could write `pnpm test:silent dancer`. +To make sure your changes didn't break any existing test cases, run `pnpm test:silent` in your terminal. You can also provide an argument to the command: to run only the Dancer (ability) tests, you could write `pnpm test:silent dancer`. - __Note that passing all test cases does *not* guarantee that everything is working properly__. The project does not have complete regression testing. -Most non-trivial changes (*especially bug fixes*) should come along with new test cases. +Most non-trivial changes (*especially bug fixes*) should come along with new test cases. - To make a new test file, run `pnpm test:create` and follow the prompts. If the move/ability/etc. you're modifying already has tests, simply add new cases to the end of the file. As mentioned before, the easiest way to get familiar with the system and understand how to write your own tests is simply to read the existing tests, particularly ones similar to the tests you intend to write. - Ensure that new tests: - Are deterministic. In other words, the test should never pass or fail when it shouldn't due to randomness. This involves primarily ensuring that abilities and moves are never randomly selected. @@ -107,4 +124,4 @@ Most non-trivial changes (*especially bug fixes*) should come along with new tes > Some issues may require you to have unlocks on your save file which go beyond normal overrides. For this reason, the repository contains a [save file](../test/test-utils/saves/everything.psrv) with _everything_ unlocked (even ones not legitimately obtainable, like unimplemented variant shinies). 1. Start the game up locally and navigate to `Menu -> Manage Data -> Import Data` -2. Select [everything.prsv](test/test-utils/saves/everything.prsv) (`test/test-utils/saves/everything.prsv`) and confirm. +2. Select [everything.prsv](test/test-utils/saves/everything.prsv) (`test/test-utils/saves/everything.prsv`) and confirm. \ No newline at end of file diff --git a/CREDITS.md b/CREDITS.md index bca89c816ca..6bd73d72901 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -24,9 +24,10 @@ - Pokémon Sword/Shield - Pokémon Legends: Arceus - Pokémon Scarlet/Violet -- Firel (Custom Graveyard, Ice Cave, Laboratory, Metropolis, Plains, Power Plant, Seabed, Space, and Volcano biome music) +- Firel (Custom Graveyard, Ice Cave, Laboratory, Metropolis, Plains, Power Plant, Seabed, Space, Volcano, and Desert biome music) - Lmz (Custom Ancient Ruins, Jungle, and Lake biome music) -- Andr06 (Custom Forest, Slum and Sea biome music) +- Andr06 (Custom Forest, Slum, Sea, and Fairy Cave biome music) +- Leavannite (Custom Wasteland biome music) - _tresnoir - unveiler diff --git a/RELEASE b/RELEASE new file mode 100644 index 00000000000..a1a9f30b0e8 --- /dev/null +++ b/RELEASE @@ -0,0 +1 @@ +Release v1.10.0 diff --git a/biome.jsonc b/biome.jsonc index d2f7c711dc9..a63ce0ee07d 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -36,7 +36,6 @@ "!**/src/data/balance/tms.ts" ] }, - "assist": { "actions": { "source": { diff --git a/package.json b/package.json index d3ea890c005..93668f15c61 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.9.6", + "version": "1.11.0", "type": "module", "scripts": { "start": "vite", @@ -14,6 +14,7 @@ "test:watch": "vitest watch --coverage --no-isolate", "test:silent": "vitest run --silent='passed-only' --no-isolate", "test:create": "node scripts/create-test/create-test.js", + "scrape-trainers": "node scripts/scrape-trainer-names/main.js", "typecheck": "tsc --noEmit", "biome": "biome check --write --changed --no-errors-on-unmatched --diagnostic-level=error", "biome-ci": "biome ci --diagnostic-level=error --reporter=github --no-errors-on-unmatched", diff --git a/public/audio/bgm/wasteland.mp3 b/public/audio/bgm/wasteland.mp3 index 646cbd89a1f..ee096af99ac 100644 Binary files a/public/audio/bgm/wasteland.mp3 and b/public/audio/bgm/wasteland.mp3 differ diff --git a/public/battle-anims/common-wind.json b/public/battle-anims/common-wind.json index f59f95c007f..7c2cbc0fb0f 100644 --- a/public/battle-anims/common-wind.json +++ b/public/battle-anims/common-wind.json @@ -1102,6 +1102,112 @@ "volume": 100, "pitch": 136, "eventType": "AnimTimedSoundEvent" + }, + { + "frameIndex": 0, + "resourceName": "PRAS- Strong Winds", + "bgX": 0, + "bgY": 0, + "opacity": 0, + "duration": 4, + "eventType": "AnimTimedAddBgEvent" + }, + { + "frameIndex": 0, + "resourceName": "", + "bgX": 0, + "bgY": 0, + "opacity": 32, + "duration": 4, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "4": [ + { + "frameIndex": 4, + "resourceName": "", + "bgX": 10, + "bgY": 0, + "opacity": 64, + "duration": 4, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "8": [ + { + "frameIndex": 8, + "resourceName": "", + "bgX": 20, + "bgY": 0, + "opacity": 128, + "duration": 4, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "12": [ + { + "frameIndex": 12, + "resourceName": "", + "bgX": 30, + "bgY": 0, + "opacity": 128, + "duration": 4, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "16": [ + { + "frameIndex": 16, + "resourceName": "", + "bgX": 40, + "bgY": 0, + "opacity": 128, + "duration": 4, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "20": [ + { + "frameIndex": 20, + "resourceName": "", + "bgX": 50, + "bgY": 0, + "opacity": 128, + "duration": 4, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "24": [ + { + "frameIndex": 24, + "resourceName": "", + "bgX": 60, + "bgY": 0, + "opacity": 64, + "duration": 4, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "28": [ + { + "frameIndex": 28, + "resourceName": "", + "bgX": 70, + "bgY": 0, + "opacity": 32, + "duration": 4, + "eventType": "AnimTimedUpdateBgEvent" + } + ], + "32": [ + { + "frameIndex": 32, + "resourceName": "", + "bgX": 80, + "bgY": 0, + "opacity": 0, + "duration": 3, + "eventType": "AnimTimedUpdateBgEvent" } ] }, diff --git a/public/images/items.json b/public/images/items.json index 7b332442f04..40c14389ab2 100644 --- a/public/images/items.json +++ b/public/images/items.json @@ -4,11 +4,32 @@ "image": "items.png", "format": "RGBA8888", "size": { - "w": 434, - "h": 434 + "w": 435, + "h": 435 }, "scale": 1, "frames": [ + { + "filename": "calendar", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 0, + "y": 1, + "w": 32, + "h": 29 + }, + "frame": { + "x": 0, + "y": 0, + "w": 32, + "h": 29 + } + }, { "filename": "galarica_cuff", "rotated": false, @@ -25,7 +46,7 @@ }, "frame": { "x": 0, - "y": 0, + "y": 29, "w": 29, "h": 30 } @@ -45,7 +66,7 @@ "h": 27 }, "frame": { - "x": 29, + "x": 32, "y": 0, "w": 32, "h": 27 @@ -67,7 +88,7 @@ }, "frame": { "x": 0, - "y": 30, + "y": 59, "w": 29, "h": 28 } @@ -87,8 +108,8 @@ "h": 28 }, "frame": { - "x": 29, - "y": 27, + "x": 64, + "y": 0, "w": 30, "h": 28 } @@ -108,8 +129,8 @@ "h": 27 }, "frame": { - "x": 61, - "y": 0, + "x": 0, + "y": 87, "w": 29, "h": 27 } @@ -129,54 +150,12 @@ "h": 28 }, "frame": { - "x": 0, - "y": 58, + "x": 94, + "y": 0, "w": 28, "h": 28 } }, - { - "filename": "bronze_ribbon", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 22, - "h": 31 - }, - "frame": { - "x": 0, - "y": 86, - "w": 22, - "h": 31 - } - }, - { - "filename": "great_ribbon", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 22, - "h": 31 - }, - "frame": { - "x": 0, - "y": 117, - "w": 22, - "h": 31 - } - }, { "filename": "linking_cord", "rotated": false, @@ -192,75 +171,12 @@ "h": 26 }, "frame": { - "x": 59, - "y": 27, + "x": 0, + "y": 114, "w": 27, "h": 26 } }, - { - "filename": "master_ribbon", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 22, - "h": 31 - }, - "frame": { - "x": 0, - "y": 148, - "w": 22, - "h": 31 - } - }, - { - "filename": "rogue_ribbon", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 22, - "h": 31 - }, - "frame": { - "x": 0, - "y": 179, - "w": 22, - "h": 31 - } - }, - { - "filename": "ultra_ribbon", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 1, - "w": 22, - "h": 31 - }, - "frame": { - "x": 0, - "y": 210, - "w": 22, - "h": 31 - } - }, { "filename": "inverse", "rotated": false, @@ -277,7 +193,7 @@ }, "frame": { "x": 0, - "y": 241, + "y": 140, "w": 22, "h": 30 } @@ -298,7 +214,7 @@ }, "frame": { "x": 0, - "y": 271, + "y": 170, "w": 22, "h": 29 } @@ -319,7 +235,7 @@ }, "frame": { "x": 0, - "y": 300, + "y": 199, "w": 22, "h": 29 } @@ -340,7 +256,7 @@ }, "frame": { "x": 0, - "y": 329, + "y": 228, "w": 22, "h": 29 } @@ -360,7 +276,7 @@ "h": 26 }, "frame": { - "x": 90, + "x": 122, "y": 0, "w": 24, "h": 26 @@ -382,7 +298,7 @@ }, "frame": { "x": 0, - "y": 358, + "y": 257, "w": 22, "h": 28 } @@ -403,13 +319,13 @@ }, "frame": { "x": 0, - "y": 386, + "y": 285, "w": 22, "h": 28 } }, { - "filename": "chipped_pot", + "filename": "ribbon_gen6", "rotated": false, "trimmed": true, "sourceSize": { @@ -417,16 +333,37 @@ "h": 32 }, "spriteSourceSize": { - "x": 3, - "y": 6, - "w": 26, - "h": 20 + "x": 5, + "y": 2, + "w": 22, + "h": 28 }, "frame": { "x": 0, - "y": 414, - "w": 26, - "h": 20 + "y": 313, + "w": 22, + "h": 28 + } + }, + { + "filename": "ribbon_gen8", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 2, + "w": 22, + "h": 28 + }, + "frame": { + "x": 0, + "y": 341, + "w": 22, + "h": 28 } }, { @@ -444,7 +381,7 @@ "h": 26 }, "frame": { - "x": 114, + "x": 146, "y": 0, "w": 23, "h": 26 @@ -465,7 +402,7 @@ "h": 22 }, "frame": { - "x": 137, + "x": 169, "y": 0, "w": 27, "h": 22 @@ -486,7 +423,7 @@ "h": 21 }, "frame": { - "x": 164, + "x": 196, "y": 0, "w": 28, "h": 21 @@ -507,7 +444,7 @@ "h": 21 }, "frame": { - "x": 192, + "x": 224, "y": 0, "w": 28, "h": 21 @@ -528,7 +465,7 @@ "h": 21 }, "frame": { - "x": 220, + "x": 252, "y": 0, "w": 28, "h": 21 @@ -549,7 +486,7 @@ "h": 21 }, "frame": { - "x": 248, + "x": 280, "y": 0, "w": 28, "h": 21 @@ -570,7 +507,7 @@ "h": 21 }, "frame": { - "x": 276, + "x": 308, "y": 0, "w": 28, "h": 21 @@ -591,96 +528,12 @@ "h": 21 }, "frame": { - "x": 304, + "x": 336, "y": 0, "w": 28, "h": 21 } }, - { - "filename": "cracked_pot", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 3, - "y": 6, - "w": 26, - "h": 20 - }, - "frame": { - "x": 332, - "y": 0, - "w": 26, - "h": 20 - } - }, - { - "filename": "legend_plate", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 3, - "y": 6, - "w": 25, - "h": 20 - }, - "frame": { - "x": 358, - "y": 0, - "w": 25, - "h": 20 - } - }, - { - "filename": "mystical_rock", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 25, - "h": 23 - }, - "frame": { - "x": 383, - "y": 0, - "w": 25, - "h": 23 - } - }, - { - "filename": "blank_plate", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 408, - "y": 0, - "w": 24, - "h": 24 - } - }, { "filename": "exp_charm", "rotated": false, @@ -696,8 +549,8 @@ "h": 31 }, "frame": { - "x": 22, - "y": 86, + "x": 0, + "y": 369, "w": 17, "h": 31 } @@ -717,12 +570,75 @@ "h": 31 }, "frame": { - "x": 22, - "y": 117, + "x": 0, + "y": 400, "w": 17, "h": 31 } }, + { + "filename": "chipped_pot", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 3, + "y": 6, + "w": 26, + "h": 20 + }, + "frame": { + "x": 364, + "y": 0, + "w": 26, + "h": 20 + } + }, + { + "filename": "cracked_pot", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 3, + "y": 6, + "w": 26, + "h": 20 + }, + "frame": { + "x": 390, + "y": 0, + "w": 26, + "h": 20 + } + }, + { + "filename": "manaphy_egg", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 19, + "h": 23 + }, + "frame": { + "x": 416, + "y": 0, + "w": 19, + "h": 23 + } + }, { "filename": "super_exp_charm", "rotated": false, @@ -739,7 +655,7 @@ }, "frame": { "x": 22, - "y": 148, + "y": 140, "w": 17, "h": 31 } @@ -760,13 +676,13 @@ }, "frame": { "x": 22, - "y": 179, + "y": 171, "w": 17, "h": 30 } }, { - "filename": "ribbon_gen6", + "filename": "common_ribbon", "rotated": false, "trimmed": true, "sourceSize": { @@ -774,20 +690,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 7, "y": 2, - "w": 22, + "w": 18, "h": 28 }, "frame": { "x": 22, - "y": 209, - "w": 22, + "y": 201, + "w": 18, "h": 28 } }, { - "filename": "ribbon_gen8", + "filename": "great_ribbon", "rotated": false, "trimmed": true, "sourceSize": { @@ -795,15 +711,78 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, + "x": 7, "y": 2, - "w": 22, + "w": 18, "h": 28 }, "frame": { "x": 22, - "y": 237, - "w": 22, + "y": 229, + "w": 18, + "h": 28 + } + }, + { + "filename": "master_ribbon", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 2, + "w": 18, + "h": 28 + }, + "frame": { + "x": 22, + "y": 257, + "w": 18, + "h": 28 + } + }, + { + "filename": "rogue_ribbon", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 2, + "w": 18, + "h": 28 + }, + "frame": { + "x": 22, + "y": 285, + "w": 18, + "h": 28 + } + }, + { + "filename": "ultra_ribbon", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 2, + "w": 18, + "h": 28 + }, + "frame": { + "x": 22, + "y": 313, + "w": 18, "h": 28 } }, @@ -823,11 +802,53 @@ }, "frame": { "x": 22, - "y": 265, + "y": 341, "w": 22, "h": 25 } }, + { + "filename": "ultranecrozium_z", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 1, + "y": 9, + "w": 30, + "h": 15 + }, + "frame": { + "x": 122, + "y": 26, + "w": 30, + "h": 15 + } + }, + { + "filename": "adamant_crystal", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 23, + "h": 21 + }, + "frame": { + "x": 152, + "y": 26, + "w": 23, + "h": 21 + } + }, { "filename": "big_root", "rotated": false, @@ -843,12 +864,33 @@ "h": 24 }, "frame": { - "x": 22, - "y": 290, + "x": 175, + "y": 22, "w": 23, "h": 24 } }, + { + "filename": "blank_plate", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 198, + "y": 21, + "w": 24, + "h": 24 + } + }, { "filename": "choice_scarf", "rotated": false, @@ -864,8 +906,8 @@ "h": 24 }, "frame": { - "x": 22, - "y": 314, + "x": 222, + "y": 21, "w": 24, "h": 24 } @@ -885,8 +927,8 @@ "h": 24 }, "frame": { - "x": 22, - "y": 338, + "x": 246, + "y": 21, "w": 24, "h": 24 } @@ -906,8 +948,8 @@ "h": 24 }, "frame": { - "x": 22, - "y": 362, + "x": 270, + "y": 21, "w": 24, "h": 24 } @@ -927,8 +969,8 @@ "h": 24 }, "frame": { - "x": 22, - "y": 386, + "x": 294, + "y": 21, "w": 24, "h": 24 } @@ -948,138 +990,12 @@ "h": 24 }, "frame": { - "x": 26, - "y": 410, + "x": 318, + "y": 21, "w": 24, "h": 24 } }, - { - "filename": "ultranecrozium_z", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 1, - "y": 9, - "w": 30, - "h": 15 - }, - "frame": { - "x": 29, - "y": 55, - "w": 30, - "h": 15 - } - }, - { - "filename": "mega_bracelet", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 16 - }, - "frame": { - "x": 28, - "y": 70, - "w": 20, - "h": 16 - } - }, - { - "filename": "choice_specs", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 24, - "h": 18 - }, - "frame": { - "x": 59, - "y": 53, - "w": 24, - "h": 18 - } - }, - { - "filename": "calcium", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 39, - "y": 86, - "w": 16, - "h": 24 - } - }, - { - "filename": "carbos", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 39, - "y": 110, - "w": 16, - "h": 24 - } - }, - { - "filename": "catching_charm", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 4, - "w": 21, - "h": 24 - }, - "frame": { - "x": 39, - "y": 134, - "w": 21, - "h": 24 - } - }, { "filename": "flame_plate", "rotated": false, @@ -1095,8 +1011,8 @@ "h": 24 }, "frame": { - "x": 39, - "y": 158, + "x": 342, + "y": 21, "w": 24, "h": 24 } @@ -1116,8 +1032,8 @@ "h": 24 }, "frame": { - "x": 39, - "y": 182, + "x": 366, + "y": 20, "w": 24, "h": 24 } @@ -1137,14 +1053,14 @@ "h": 24 }, "frame": { - "x": 44, - "y": 206, + "x": 390, + "y": 20, "w": 24, "h": 24 } }, { - "filename": "gracidea", + "filename": "catching_charm", "rotated": false, "trimmed": true, "sourceSize": { @@ -1152,20 +1068,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, + "x": 5, "y": 4, - "w": 24, + "w": 21, "h": 24 }, "frame": { - "x": 44, - "y": 230, - "w": 24, + "x": 414, + "y": 23, + "w": 21, "h": 24 } }, { - "filename": "grip_claw", + "filename": "calcium", "rotated": false, "trimmed": true, "sourceSize": { @@ -1173,20 +1089,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, + "x": 8, "y": 4, - "w": 24, + "w": 16, "h": 24 }, "frame": { - "x": 44, - "y": 254, - "w": 24, + "x": 17, + "y": 369, + "w": 16, "h": 24 } }, { - "filename": "icicle_plate", + "filename": "carbos", "rotated": false, "trimmed": true, "sourceSize": { @@ -1194,20 +1110,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, + "x": 8, "y": 4, - "w": 24, + "w": 16, "h": 24 }, "frame": { - "x": 45, - "y": 278, - "w": 24, + "x": 17, + "y": 393, + "w": 16, "h": 24 } }, { - "filename": "insect_plate", + "filename": "choice_specs", "rotated": false, "trimmed": true, "sourceSize": { @@ -1216,99 +1132,15 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, + "y": 8, "w": 24, - "h": 24 + "h": 18 }, "frame": { - "x": 46, - "y": 302, + "x": 17, + "y": 417, "w": 24, - "h": 24 - } - }, - { - "filename": "iron_plate", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 46, - "y": 326, - "w": 24, - "h": 24 - } - }, - { - "filename": "lucky_punch", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 46, - "y": 350, - "w": 24, - "h": 24 - } - }, - { - "filename": "lucky_punch_great", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 4, - "w": 24, - "h": 24 - }, - "frame": { - "x": 46, - "y": 374, - "w": 24, - "h": 24 - } - }, - { - "filename": "silver_powder", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 11, - "w": 24, - "h": 15 - }, - "frame": { - "x": 48, - "y": 71, - "w": 24, - "h": 15 + "h": 18 } }, { @@ -1326,8 +1158,8 @@ "h": 24 }, "frame": { - "x": 55, - "y": 86, + "x": 33, + "y": 366, "w": 18, "h": 24 } @@ -1347,12 +1179,33 @@ "h": 24 }, "frame": { - "x": 55, - "y": 110, + "x": 33, + "y": 390, "w": 18, "h": 24 } }, + { + "filename": "golden_net", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 24, + "h": 21 + }, + "frame": { + "x": 41, + "y": 414, + "w": 24, + "h": 21 + } + }, { "filename": "full_restore", "rotated": false, @@ -1368,12 +1221,327 @@ "h": 24 }, "frame": { - "x": 60, - "y": 134, + "x": 29, + "y": 29, "w": 18, "h": 24 } }, + { + "filename": "gracidea", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 29, + "y": 53, + "w": 24, + "h": 24 + } + }, + { + "filename": "grip_claw", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 29, + "y": 77, + "w": 24, + "h": 24 + } + }, + { + "filename": "lure", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 17, + "h": 24 + }, + "frame": { + "x": 47, + "y": 27, + "w": 17, + "h": 24 + } + }, + { + "filename": "mystical_rock", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 25, + "h": 23 + }, + "frame": { + "x": 64, + "y": 28, + "w": 25, + "h": 23 + } + }, + { + "filename": "clefairy_doll", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 24, + "h": 23 + }, + "frame": { + "x": 89, + "y": 28, + "w": 24, + "h": 23 + } + }, + { + "filename": "icicle_plate", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 53, + "y": 51, + "w": 24, + "h": 24 + } + }, + { + "filename": "insect_plate", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 53, + "y": 75, + "w": 24, + "h": 24 + } + }, + { + "filename": "iron_plate", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 77, + "y": 51, + "w": 24, + "h": 24 + } + }, + { + "filename": "lucky_punch", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 77, + "y": 75, + "w": 24, + "h": 24 + } + }, + { + "filename": "ability_capsule", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 9, + "w": 24, + "h": 14 + }, + "frame": { + "x": 29, + "y": 101, + "w": 24, + "h": 14 + } + }, + { + "filename": "lucky_punch_great", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 24, + "h": 24 + }, + "frame": { + "x": 27, + "y": 115, + "w": 24, + "h": 24 + } + }, + { + "filename": "legend_plate", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 3, + "y": 6, + "w": 25, + "h": 20 + }, + "frame": { + "x": 53, + "y": 99, + "w": 25, + "h": 20 + } + }, + { + "filename": "amulet_coin", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 23, + "h": 21 + }, + "frame": { + "x": 78, + "y": 99, + "w": 23, + "h": 21 + } + }, + { + "filename": "coin_case", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 24, + "h": 23 + }, + "frame": { + "x": 51, + "y": 119, + "w": 24, + "h": 23 + } + }, + { + "filename": "exp_balance", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 24, + "h": 22 + }, + "frame": { + "x": 75, + "y": 120, + "w": 24, + "h": 22 + } + }, { "filename": "hp_up", "rotated": false, @@ -1389,8 +1557,8 @@ "h": 24 }, "frame": { - "x": 63, - "y": 158, + "x": 101, + "y": 51, "w": 16, "h": 24 } @@ -1410,14 +1578,14 @@ "h": 24 }, "frame": { - "x": 63, - "y": 182, + "x": 101, + "y": 75, "w": 16, "h": 24 } }, { - "filename": "kings_rock", + "filename": "auspicious_armor", "rotated": false, "trimmed": true, "sourceSize": { @@ -1425,16 +1593,37 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 4, + "x": 4, + "y": 5, "w": 23, - "h": 24 + "h": 21 }, "frame": { - "x": 68, - "y": 206, + "x": 101, + "y": 99, "w": 23, - "h": 24 + "h": 21 + } + }, + { + "filename": "exp_share", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 24, + "h": 22 + }, + "frame": { + "x": 99, + "y": 120, + "w": 24, + "h": 22 } }, { @@ -1452,8 +1641,8 @@ "h": 24 }, "frame": { - "x": 68, - "y": 230, + "x": 39, + "y": 142, "w": 24, "h": 24 } @@ -1473,8 +1662,8 @@ "h": 24 }, "frame": { - "x": 68, - "y": 254, + "x": 39, + "y": 166, "w": 24, "h": 24 } @@ -1494,8 +1683,8 @@ "h": 24 }, "frame": { - "x": 69, - "y": 278, + "x": 63, + "y": 142, "w": 24, "h": 24 } @@ -1515,8 +1704,8 @@ "h": 24 }, "frame": { - "x": 70, - "y": 302, + "x": 87, + "y": 142, "w": 24, "h": 24 } @@ -1536,8 +1725,8 @@ "h": 24 }, "frame": { - "x": 70, - "y": 326, + "x": 63, + "y": 166, "w": 24, "h": 24 } @@ -1557,8 +1746,8 @@ "h": 24 }, "frame": { - "x": 70, - "y": 350, + "x": 87, + "y": 166, "w": 24, "h": 24 } @@ -1578,8 +1767,8 @@ "h": 24 }, "frame": { - "x": 70, - "y": 374, + "x": 40, + "y": 190, "w": 24, "h": 24 } @@ -1599,75 +1788,12 @@ "h": 24 }, "frame": { - "x": 50, - "y": 398, + "x": 40, + "y": 214, "w": 24, "h": 24 } }, - { - "filename": "max_revive", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 4, - "w": 22, - "h": 24 - }, - "frame": { - "x": 74, - "y": 398, - "w": 22, - "h": 24 - } - }, - { - "filename": "ability_capsule", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 9, - "w": 24, - "h": 14 - }, - "frame": { - "x": 137, - "y": 22, - "w": 24, - "h": 14 - } - }, - { - "filename": "lure", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 17, - "h": 24 - }, - "frame": { - "x": 86, - "y": 27, - "w": 17, - "h": 24 - } - }, { "filename": "scanner", "rotated": false, @@ -1683,138 +1809,12 @@ "h": 24 }, "frame": { - "x": 103, - "y": 26, + "x": 64, + "y": 190, "w": 24, "h": 24 } }, - { - "filename": "clefairy_doll", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 24, - "h": 23 - }, - "frame": { - "x": 127, - "y": 36, - "w": 24, - "h": 23 - } - }, - { - "filename": "coin_case", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 24, - "h": 23 - }, - "frame": { - "x": 103, - "y": 50, - "w": 24, - "h": 23 - } - }, - { - "filename": "big_nugget", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 - }, - "frame": { - "x": 83, - "y": 53, - "w": 20, - "h": 20 - } - }, - { - "filename": "dragon_scale", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 24, - "h": 18 - }, - "frame": { - "x": 127, - "y": 59, - "w": 24, - "h": 18 - } - }, - { - "filename": "max_elixir", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 18, - "h": 24 - }, - "frame": { - "x": 151, - "y": 36, - "w": 18, - "h": 24 - } - }, - { - "filename": "adamant_crystal", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 23, - "h": 21 - }, - "frame": { - "x": 151, - "y": 60, - "w": 23, - "h": 21 - } - }, { "filename": "silk_scarf", "rotated": false, @@ -1830,8 +1830,8 @@ "h": 24 }, "frame": { - "x": 169, - "y": 21, + "x": 40, + "y": 238, "w": 24, "h": 24 } @@ -1851,8 +1851,8 @@ "h": 24 }, "frame": { - "x": 193, - "y": 21, + "x": 64, + "y": 214, "w": 24, "h": 24 } @@ -1872,8 +1872,8 @@ "h": 24 }, "frame": { - "x": 217, - "y": 21, + "x": 40, + "y": 262, "w": 24, "h": 24 } @@ -1893,8 +1893,8 @@ "h": 24 }, "frame": { - "x": 241, - "y": 21, + "x": 64, + "y": 238, "w": 24, "h": 24 } @@ -1914,8 +1914,8 @@ "h": 24 }, "frame": { - "x": 265, - "y": 21, + "x": 40, + "y": 286, "w": 24, "h": 24 } @@ -1935,33 +1935,12 @@ "h": 24 }, "frame": { - "x": 289, - "y": 21, + "x": 64, + "y": 262, "w": 24, "h": 24 } }, - { - "filename": "oval_charm", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 21, - "h": 24 - }, - "frame": { - "x": 313, - "y": 21, - "w": 21, - "h": 24 - } - }, { "filename": "toxic_plate", "rotated": false, @@ -1977,8 +1956,8 @@ "h": 24 }, "frame": { - "x": 334, - "y": 20, + "x": 40, + "y": 310, "w": 24, "h": 24 } @@ -1998,75 +1977,12 @@ "h": 24 }, "frame": { - "x": 358, - "y": 20, + "x": 64, + "y": 286, "w": 24, "h": 24 } }, - { - "filename": "exp_balance", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 24, - "h": 22 - }, - "frame": { - "x": 382, - "y": 23, - "w": 24, - "h": 22 - } - }, - { - "filename": "exp_share", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 24, - "h": 22 - }, - "frame": { - "x": 406, - "y": 24, - "w": 24, - "h": 22 - } - }, - { - "filename": "candy_overlay", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 12, - "w": 16, - "h": 15 - }, - "frame": { - "x": 169, - "y": 45, - "w": 16, - "h": 15 - } - }, { "filename": "expert_belt", "rotated": false, @@ -2082,12 +1998,117 @@ "h": 23 }, "frame": { - "x": 185, - "y": 45, + "x": 64, + "y": 310, "w": 24, "h": 23 } }, + { + "filename": "kings_rock", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 4, + "w": 23, + "h": 24 + }, + "frame": { + "x": 88, + "y": 190, + "w": 23, + "h": 24 + } + }, + { + "filename": "reveal_glass", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 23, + "h": 24 + }, + "frame": { + "x": 88, + "y": 214, + "w": 23, + "h": 24 + } + }, + { + "filename": "berry_pouch", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 5, + "w": 23, + "h": 23 + }, + "frame": { + "x": 88, + "y": 238, + "w": 23, + "h": 23 + } + }, + { + "filename": "dynamax_band", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 4, + "w": 23, + "h": 23 + }, + "frame": { + "x": 88, + "y": 261, + "w": 23, + "h": 23 + } + }, + { + "filename": "griseous_core", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 23, + "h": 23 + }, + "frame": { + "x": 88, + "y": 284, + "w": 23, + "h": 23 + } + }, { "filename": "hearthflame_mask", "rotated": false, @@ -2103,12 +2124,54 @@ "h": 23 }, "frame": { - "x": 209, - "y": 45, + "x": 88, + "y": 307, "w": 24, "h": 23 } }, + { + "filename": "max_revive", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 4, + "w": 22, + "h": 24 + }, + "frame": { + "x": 44, + "y": 334, + "w": 22, + "h": 24 + } + }, + { + "filename": "black_belt", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 66, + "y": 333, + "w": 22, + "h": 23 + } + }, { "filename": "leppa_berry", "rotated": false, @@ -2124,12 +2187,201 @@ "h": 23 }, "frame": { - "x": 233, - "y": 45, + "x": 88, + "y": 330, "w": 24, "h": 23 } }, + { + "filename": "max_elixir", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 4, + "w": 18, + "h": 24 + }, + "frame": { + "x": 111, + "y": 142, + "w": 18, + "h": 24 + } + }, + { + "filename": "max_ether", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 4, + "w": 18, + "h": 24 + }, + "frame": { + "x": 111, + "y": 166, + "w": 18, + "h": 24 + } + }, + { + "filename": "max_potion", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 4, + "w": 18, + "h": 24 + }, + "frame": { + "x": 111, + "y": 190, + "w": 18, + "h": 24 + } + }, + { + "filename": "oval_charm", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 21, + "h": 24 + }, + "frame": { + "x": 111, + "y": 214, + "w": 21, + "h": 24 + } + }, + { + "filename": "shiny_charm", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 21, + "h": 24 + }, + "frame": { + "x": 111, + "y": 238, + "w": 21, + "h": 24 + } + }, + { + "filename": "bug_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 111, + "y": 262, + "w": 22, + "h": 23 + } + }, + { + "filename": "bug_memory", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 111, + "y": 285, + "w": 22, + "h": 22 + } + }, + { + "filename": "dark_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 112, + "y": 307, + "w": 22, + "h": 23 + } + }, + { + "filename": "dragon_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 112, + "y": 330, + "w": 22, + "h": 23 + } + }, { "filename": "scope_lens", "rotated": false, @@ -2145,8 +2397,8 @@ "h": 23 }, "frame": { - "x": 257, - "y": 45, + "x": 117, + "y": 41, "w": 24, "h": 23 } @@ -2166,14 +2418,14 @@ "h": 23 }, "frame": { - "x": 281, - "y": 45, + "x": 117, + "y": 64, "w": 24, "h": 23 } }, { - "filename": "berry_pouch", + "filename": "leek", "rotated": false, "trimmed": true, "sourceSize": { @@ -2187,14 +2439,14 @@ "h": 23 }, "frame": { - "x": 305, - "y": 45, + "x": 141, + "y": 47, "w": 23, "h": 23 } }, { - "filename": "black_belt", + "filename": "binding_band", "rotated": false, "trimmed": true, "sourceSize": { @@ -2203,19 +2455,61 @@ }, "spriteSourceSize": { "x": 5, - "y": 4, - "w": 22, - "h": 23 + "y": 6, + "w": 23, + "h": 20 }, "frame": { - "x": 328, - "y": 45, - "w": 22, - "h": 23 + "x": 141, + "y": 70, + "w": 23, + "h": 20 } }, { - "filename": "reveal_glass", + "filename": "max_lure", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 17, + "h": 24 + }, + "frame": { + "x": 164, + "y": 47, + "w": 17, + "h": 24 + } + }, + { + "filename": "red_orb", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 20, + "h": 24 + }, + "frame": { + "x": 181, + "y": 46, + "w": 20, + "h": 24 + } + }, + { + "filename": "macho_brace", "rotated": false, "trimmed": true, "sourceSize": { @@ -2224,33 +2518,12 @@ }, "spriteSourceSize": { "x": 4, - "y": 4, - "w": 23, - "h": 24 - }, - "frame": { - "x": 350, - "y": 44, - "w": 23, - "h": 24 - } - }, - { - "filename": "dynamax_band", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 4, + "y": 5, "w": 23, "h": 23 }, "frame": { - "x": 373, + "x": 201, "y": 45, "w": 23, "h": 23 @@ -2271,98 +2544,14 @@ "h": 22 }, "frame": { - "x": 396, - "y": 46, + "x": 224, + "y": 45, "w": 24, "h": 22 } }, { - "filename": "revive", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 10, - "y": 8, - "w": 12, - "h": 17 - }, - "frame": { - "x": 420, - "y": 46, - "w": 12, - "h": 17 - } - }, - { - "filename": "golden_net", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 24, - "h": 21 - }, - "frame": { - "x": 174, - "y": 68, - "w": 24, - "h": 21 - } - }, - { - "filename": "amulet_coin", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 23, - "h": 21 - }, - "frame": { - "x": 198, - "y": 68, - "w": 23, - "h": 21 - } - }, - { - "filename": "auspicious_armor", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 23, - "h": 21 - }, - "frame": { - "x": 221, - "y": 68, - "w": 23, - "h": 21 - } - }, - { - "filename": "griseous_core", + "filename": "healing_charm", "rotated": false, "trimmed": true, "sourceSize": { @@ -2373,55 +2562,13 @@ "x": 5, "y": 5, "w": 23, - "h": 23 + "h": 22 }, "frame": { - "x": 244, - "y": 68, + "x": 248, + "y": 45, "w": 23, - "h": 23 - } - }, - { - "filename": "leek", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 23, - "h": 23 - }, - "frame": { - "x": 267, - "y": 68, - "w": 23, - "h": 23 - } - }, - { - "filename": "macho_brace", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 23, - "h": 23 - }, - "frame": { - "x": 290, - "y": 68, - "w": 23, - "h": 23 + "h": 22 } }, { @@ -2439,8 +2586,8 @@ "h": 23 }, "frame": { - "x": 313, - "y": 68, + "x": 271, + "y": 45, "w": 23, "h": 23 } @@ -2460,285 +2607,12 @@ "h": 23 }, "frame": { - "x": 336, - "y": 68, + "x": 294, + "y": 45, "w": 23, "h": 23 } }, - { - "filename": "bug_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 359, - "y": 68, - "w": 22, - "h": 23 - } - }, - { - "filename": "dark_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 381, - "y": 68, - "w": 22, - "h": 23 - } - }, - { - "filename": "dragon_fang", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 21, - "h": 23 - }, - "frame": { - "x": 403, - "y": 68, - "w": 21, - "h": 23 - } - }, - { - "filename": "relic_gold", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 9, - "y": 11, - "w": 15, - "h": 11 - }, - "frame": { - "x": 50, - "y": 422, - "w": 15, - "h": 11 - } - }, - { - "filename": "icy_reins_of_unity", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 24, - "h": 20 - }, - "frame": { - "x": 91, - "y": 73, - "w": 24, - "h": 20 - } - }, - { - "filename": "max_ether", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 18, - "h": 24 - }, - "frame": { - "x": 73, - "y": 73, - "w": 18, - "h": 24 - } - }, - { - "filename": "max_potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 4, - "w": 18, - "h": 24 - }, - "frame": { - "x": 73, - "y": 97, - "w": 18, - "h": 24 - } - }, - { - "filename": "dragon_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 91, - "y": 93, - "w": 22, - "h": 23 - } - }, - { - "filename": "metal_powder", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 24, - "h": 20 - }, - "frame": { - "x": 115, - "y": 77, - "w": 24, - "h": 20 - } - }, - { - "filename": "quick_powder", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 24, - "h": 20 - }, - "frame": { - "x": 113, - "y": 97, - "w": 24, - "h": 20 - } - }, - { - "filename": "berry_juice_bad", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 21 - }, - "frame": { - "x": 91, - "y": 116, - "w": 22, - "h": 21 - } - }, - { - "filename": "rusted_shield", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 24, - "h": 20 - }, - "frame": { - "x": 113, - "y": 117, - "w": 24, - "h": 20 - } - }, - { - "filename": "moon_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 23, - "h": 21 - }, - "frame": { - "x": 78, - "y": 137, - "w": 23, - "h": 21 - } - }, { "filename": "electric_tera_shard", "rotated": false, @@ -2754,8 +2628,8 @@ "h": 23 }, "frame": { - "x": 79, - "y": 158, + "x": 317, + "y": 45, "w": 22, "h": 23 } @@ -2775,12 +2649,75 @@ "h": 23 }, "frame": { - "x": 101, - "y": 137, + "x": 339, + "y": 45, "w": 22, "h": 23 } }, + { + "filename": "apicot_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 19, + "h": 20 + }, + "frame": { + "x": 164, + "y": 71, + "w": 19, + "h": 20 + } + }, + { + "filename": "berry_juice_bad", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 21 + }, + "frame": { + "x": 183, + "y": 70, + "w": 22, + "h": 21 + } + }, + { + "filename": "dragon_fang", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 21, + "h": 23 + }, + "frame": { + "x": 205, + "y": 68, + "w": 21, + "h": 23 + } + }, { "filename": "fighting_tera_shard", "rotated": false, @@ -2796,470 +2733,8 @@ "h": 23 }, "frame": { - "x": 79, - "y": 181, - "w": 22, - "h": 23 - } - }, - { - "filename": "fire_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 101, - "y": 160, - "w": 22, - "h": 23 - } - }, - { - "filename": "berry_juice_good", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 21 - }, - "frame": { - "x": 101, - "y": 183, - "w": 22, - "h": 21 - } - }, - { - "filename": "fire_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 91, - "y": 204, - "w": 22, - "h": 23 - } - }, - { - "filename": "shiny_charm", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 21, - "h": 24 - }, - "frame": { - "x": 92, - "y": 227, - "w": 21, - "h": 24 - } - }, - { - "filename": "focus_sash", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 92, - "y": 251, - "w": 22, - "h": 23 - } - }, - { - "filename": "ghost_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 93, - "y": 274, - "w": 22, - "h": 23 - } - }, - { - "filename": "grass_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 94, - "y": 297, - "w": 22, - "h": 23 - } - }, - { - "filename": "ground_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 94, - "y": 320, - "w": 22, - "h": 23 - } - }, - { - "filename": "ice_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 94, - "y": 343, - "w": 22, - "h": 23 - } - }, - { - "filename": "never_melt_ice", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 94, - "y": 366, - "w": 22, - "h": 23 - } - }, - { - "filename": "max_lure", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 17, - "h": 24 - }, - "frame": { - "x": 123, - "y": 137, - "w": 17, - "h": 24 - } - }, - { - "filename": "red_orb", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 20, - "h": 24 - }, - "frame": { - "x": 123, - "y": 161, - "w": 20, - "h": 24 - } - }, - { - "filename": "binding_band", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 23, - "h": 20 - }, - "frame": { - "x": 123, - "y": 185, - "w": 23, - "h": 20 - } - }, - { - "filename": "healing_charm", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 23, - "h": 22 - }, - "frame": { - "x": 113, - "y": 205, - "w": 23, - "h": 22 - } - }, - { - "filename": "normal_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 113, - "y": 227, - "w": 22, - "h": 23 - } - }, - { - "filename": "lansat_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 4, - "w": 21, - "h": 23 - }, - "frame": { - "x": 114, - "y": 250, - "w": 21, - "h": 23 - } - }, - { - "filename": "leaf_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 21, - "h": 23 - }, - "frame": { - "x": 115, - "y": 273, - "w": 21, - "h": 23 - } - }, - { - "filename": "mystic_water", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 20, - "h": 23 - }, - "frame": { - "x": 116, - "y": 296, - "w": 20, - "h": 23 - } - }, - { - "filename": "petaya_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 116, - "y": 319, - "w": 22, - "h": 23 - } - }, - { - "filename": "poison_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 116, - "y": 342, - "w": 22, - "h": 23 - } - }, - { - "filename": "psychic_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 116, - "y": 365, - "w": 22, - "h": 23 - } - }, - { - "filename": "reaper_cloth", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 23 - }, - "frame": { - "x": 96, - "y": 389, + "x": 226, + "y": 67, "w": 22, "h": 23 } @@ -3279,14 +2754,14 @@ "h": 22 }, "frame": { - "x": 96, - "y": 412, + "x": 248, + "y": 67, "w": 23, "h": 22 } }, { - "filename": "rock_tera_shard", + "filename": "icy_reins_of_unity", "rotated": false, "trimmed": true, "sourceSize": { @@ -3294,20 +2769,104 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, - "y": 4, + "x": 4, + "y": 7, + "w": 24, + "h": 20 + }, + "frame": { + "x": 271, + "y": 68, + "w": 24, + "h": 20 + } + }, + { + "filename": "metal_powder", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 24, + "h": 20 + }, + "frame": { + "x": 295, + "y": 68, + "w": 24, + "h": 20 + } + }, + { + "filename": "quick_powder", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 24, + "h": 20 + }, + "frame": { + "x": 319, + "y": 68, + "w": 24, + "h": 20 + } + }, + { + "filename": "berry_juice_good", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 21 + }, + "frame": { + "x": 343, + "y": 68, + "w": 22, + "h": 21 + } + }, + { + "filename": "fire_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, "w": 22, "h": 23 }, "frame": { - "x": 118, - "y": 388, + "x": 361, + "y": 45, "w": 22, "h": 23 } }, { - "filename": "steel_tera_shard", + "filename": "fire_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3321,8 +2880,8 @@ "h": 23 }, "frame": { - "x": 119, - "y": 411, + "x": 383, + "y": 44, "w": 22, "h": 23 } @@ -3342,35 +2901,14 @@ "h": 22 }, "frame": { - "x": 136, - "y": 205, + "x": 365, + "y": 68, "w": 18, "h": 22 } }, { - "filename": "sharp_beak", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 21, - "h": 23 - }, - "frame": { - "x": 135, - "y": 227, - "w": 21, - "h": 23 - } - }, - { - "filename": "stellar_tera_shard", + "filename": "flying_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3384,35 +2922,14 @@ "h": 23 }, "frame": { - "x": 135, - "y": 250, + "x": 383, + "y": 67, "w": 22, "h": 23 } }, { - "filename": "water_tera_shard", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 22, - "h": 23 - }, - "frame": { - "x": 136, - "y": 273, - "w": 22, - "h": 23 - } - }, - { - "filename": "wide_lens", + "filename": "focus_sash", "rotated": false, "trimmed": true, "sourceSize": { @@ -3426,54 +2943,12 @@ "h": 23 }, "frame": { - "x": 136, - "y": 296, + "x": 405, + "y": 47, "w": 22, "h": 23 } }, - { - "filename": "whipped_dream", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 4, - "w": 21, - "h": 23 - }, - "frame": { - "x": 138, - "y": 319, - "w": 21, - "h": 23 - } - }, - { - "filename": "bug_memory", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 138, - "y": 342, - "w": 22, - "h": 22 - } - }, { "filename": "charcoal", "rotated": false, @@ -3489,96 +2964,12 @@ "h": 22 }, "frame": { - "x": 138, - "y": 364, + "x": 405, + "y": 70, "w": 22, "h": 22 } }, - { - "filename": "dark_memory", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 140, - "y": 386, - "w": 22, - "h": 22 - } - }, - { - "filename": "dire_hit", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 141, - "y": 408, - "w": 22, - "h": 22 - } - }, - { - "filename": "blue_orb", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 - }, - "frame": { - "x": 154, - "y": 81, - "w": 20, - "h": 20 - } - }, - { - "filename": "full_heal", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 9, - "y": 4, - "w": 15, - "h": 23 - }, - "frame": { - "x": 139, - "y": 81, - "w": 15, - "h": 23 - } - }, { "filename": "super_lure", "rotated": false, @@ -3594,14 +2985,14 @@ "h": 24 }, "frame": { - "x": 137, - "y": 104, + "x": 124, + "y": 87, "w": 17, "h": 24 } }, { - "filename": "dna_splicers", + "filename": "moon_stone", "rotated": false, "trimmed": true, "sourceSize": { @@ -3609,20 +3000,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 4, + "y": 6, + "w": 23, + "h": 21 }, "frame": { - "x": 154, - "y": 101, - "w": 22, - "h": 22 + "x": 141, + "y": 90, + "w": 23, + "h": 21 } }, { - "filename": "dragon_memory", + "filename": "rusted_shield", "rotated": false, "trimmed": true, "sourceSize": { @@ -3630,37 +3021,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 + "x": 4, + "y": 6, + "w": 24, + "h": 20 }, "frame": { - "x": 176, - "y": 89, - "w": 22, - "h": 22 - } - }, - { - "filename": "electirizer", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 198, - "y": 89, - "w": 22, - "h": 22 + "x": 164, + "y": 91, + "w": 24, + "h": 20 } }, { @@ -3678,12 +3048,243 @@ "h": 20 }, "frame": { - "x": 220, - "y": 89, + "x": 188, + "y": 91, "w": 24, "h": 20 } }, + { + "filename": "big_nugget", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 20, + "h": 20 + }, + "frame": { + "x": 212, + "y": 91, + "w": 20, + "h": 20 + } + }, + { + "filename": "common_egg", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 20, + "h": 22 + }, + "frame": { + "x": 232, + "y": 90, + "w": 20, + "h": 22 + } + }, + { + "filename": "ghost_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 252, + "y": 89, + "w": 22, + "h": 23 + } + }, + { + "filename": "grass_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 274, + "y": 88, + "w": 22, + "h": 23 + } + }, + { + "filename": "ground_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 296, + "y": 88, + "w": 22, + "h": 23 + } + }, + { + "filename": "ice_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 318, + "y": 88, + "w": 22, + "h": 23 + } + }, + { + "filename": "dark_memory", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 340, + "y": 89, + "w": 22, + "h": 22 + } + }, + { + "filename": "n_lunarizer", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 6, + "w": 23, + "h": 21 + }, + "frame": { + "x": 362, + "y": 90, + "w": 23, + "h": 21 + } + }, + { + "filename": "dawn_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 20, + "h": 21 + }, + "frame": { + "x": 385, + "y": 90, + "w": 20, + "h": 21 + } + }, + { + "filename": "black_sludge", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 22, + "h": 19 + }, + "frame": { + "x": 405, + "y": 92, + "w": 22, + "h": 19 + } + }, + { + "filename": "dragon_scale", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 24, + "h": 18 + }, + "frame": { + "x": 124, + "y": 111, + "w": 24, + "h": 18 + } + }, { "filename": "shadow_reins_of_unity", "rotated": false, @@ -3699,8 +3300,8 @@ "h": 20 }, "frame": { - "x": 244, - "y": 91, + "x": 148, + "y": 111, "w": 24, "h": 20 } @@ -3720,33 +3321,12 @@ "h": 20 }, "frame": { - "x": 268, - "y": 91, + "x": 172, + "y": 111, "w": 24, "h": 20 } }, - { - "filename": "n_lunarizer", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 6, - "w": 23, - "h": 21 - }, - "frame": { - "x": 292, - "y": 91, - "w": 23, - "h": 21 - } - }, { "filename": "n_solarizer", "rotated": false, @@ -3762,119 +3342,35 @@ "h": 21 }, "frame": { - "x": 315, - "y": 91, - "w": 23, - "h": 21 - } - }, - { - "filename": "wellspring_mask", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 5, - "w": 23, - "h": 21 - }, - "frame": { - "x": 338, - "y": 91, - "w": 23, - "h": 21 - } - }, - { - "filename": "deep_sea_tooth", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 21 - }, - "frame": { - "x": 361, - "y": 91, - "w": 22, - "h": 21 - } - }, - { - "filename": "electric_memory", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 383, - "y": 91, - "w": 22, - "h": 22 - } - }, - { - "filename": "enigma_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 405, - "y": 91, - "w": 22, - "h": 22 - } - }, - { - "filename": "black_glasses", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 23, - "h": 17 - }, - "frame": { - "x": 176, + "x": 196, "y": 111, "w": 23, - "h": 17 + "h": 21 } }, { - "filename": "black_sludge", + "filename": "max_repel", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 16, + "h": 24 + }, + "frame": { + "x": 51, + "y": 358, + "w": 16, + "h": 24 + } + }, + { + "filename": "lansat_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -3883,15 +3379,162 @@ }, "spriteSourceSize": { "x": 5, - "y": 7, - "w": 22, - "h": 19 + "y": 4, + "w": 21, + "h": 23 }, "frame": { - "x": 199, - "y": 111, + "x": 67, + "y": 356, + "w": 21, + "h": 23 + } + }, + { + "filename": "never_melt_ice", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, "w": 22, - "h": 19 + "h": 23 + }, + "frame": { + "x": 88, + "y": 353, + "w": 22, + "h": 23 + } + }, + { + "filename": "normal_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 110, + "y": 353, + "w": 22, + "h": 23 + } + }, + { + "filename": "pp_max", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 16, + "h": 24 + }, + "frame": { + "x": 51, + "y": 382, + "w": 16, + "h": 24 + } + }, + { + "filename": "leaf_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 21, + "h": 23 + }, + "frame": { + "x": 67, + "y": 379, + "w": 21, + "h": 23 + } + }, + { + "filename": "petaya_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 23 + }, + "frame": { + "x": 88, + "y": 376, + "w": 22, + "h": 23 + } + }, + { + "filename": "poison_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 110, + "y": 376, + "w": 22, + "h": 23 + } + }, + { + "filename": "lock_capsule", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 19, + "h": 22 + }, + "frame": { + "x": 129, + "y": 129, + "w": 19, + "h": 22 } }, { @@ -3909,14 +3552,14 @@ "h": 20 }, "frame": { - "x": 221, - "y": 109, + "x": 148, + "y": 131, "w": 23, "h": 20 } }, { - "filename": "coupon", + "filename": "psychic_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -3924,83 +3567,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 19 + "x": 6, + "y": 4, + "w": 22, + "h": 23 }, "frame": { - "x": 244, - "y": 111, - "w": 23, - "h": 19 + "x": 129, + "y": 151, + "w": 22, + "h": 23 } }, { - "filename": "golden_mystic_ticket", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 19 - }, - "frame": { - "x": 267, - "y": 111, - "w": 23, - "h": 19 - } - }, - { - "filename": "mystic_ticket", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 19 - }, - "frame": { - "x": 290, - "y": 112, - "w": 23, - "h": 19 - } - }, - { - "filename": "pair_of_tickets", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 19 - }, - "frame": { - "x": 313, - "y": 112, - "w": 23, - "h": 19 - } - }, - { - "filename": "shell_bell", + "filename": "reaper_cloth", "rotated": false, "trimmed": true, "sourceSize": { @@ -4009,15 +3589,99 @@ }, "spriteSourceSize": { "x": 5, - "y": 7, - "w": 23, - "h": 20 + "y": 5, + "w": 22, + "h": 23 }, "frame": { - "x": 336, - "y": 112, + "x": 129, + "y": 174, + "w": 22, + "h": 23 + } + }, + { + "filename": "mystic_water", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 20, + "h": 23 + }, + "frame": { + "x": 151, + "y": 151, + "w": 20, + "h": 23 + } + }, + { + "filename": "rock_tera_shard", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 171, + "y": 131, + "w": 22, + "h": 23 + } + }, + { + "filename": "sharp_beak", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 21, + "h": 23 + }, + "frame": { + "x": 151, + "y": 174, + "w": 21, + "h": 23 + } + }, + { + "filename": "black_glasses", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, "w": 23, - "h": 20 + "h": 17 + }, + "frame": { + "x": 129, + "y": 197, + "w": 23, + "h": 17 } }, { @@ -4035,14 +3699,14 @@ "h": 20 }, "frame": { - "x": 359, - "y": 112, + "x": 171, + "y": 154, "w": 22, "h": 20 } }, { - "filename": "blunder_policy", + "filename": "steel_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -4050,20 +3714,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 6, + "x": 6, + "y": 4, "w": 22, - "h": 19 + "h": 23 }, "frame": { - "x": 381, - "y": 113, + "x": 172, + "y": 174, "w": 22, - "h": 19 + "h": 23 } }, { - "filename": "dubious_disc", + "filename": "stellar_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -4071,20 +3735,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 7, + "x": 6, + "y": 4, "w": 22, - "h": 19 + "h": 23 }, "frame": { - "x": 403, - "y": 113, + "x": 132, + "y": 214, "w": 22, - "h": 19 + "h": 23 } }, { - "filename": "fairy_feather", + "filename": "water_tera_shard", "rotated": false, "trimmed": true, "sourceSize": { @@ -4092,16 +3756,16 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 7, + "x": 6, + "y": 4, "w": 22, - "h": 20 + "h": 23 }, "frame": { - "x": 154, - "y": 123, + "x": 132, + "y": 237, "w": 22, - "h": 20 + "h": 23 } }, { @@ -4119,14 +3783,14 @@ "h": 17 }, "frame": { - "x": 176, - "y": 128, + "x": 152, + "y": 197, "w": 23, "h": 17 } }, { - "filename": "chill_drive", + "filename": "whipped_dream", "rotated": false, "trimmed": true, "sourceSize": { @@ -4134,16 +3798,205 @@ "h": 32 }, "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 23, - "h": 17 + "x": 5, + "y": 4, + "w": 21, + "h": 23 }, "frame": { - "x": 199, - "y": 130, - "w": 23, - "h": 17 + "x": 154, + "y": 214, + "w": 21, + "h": 23 + } + }, + { + "filename": "wide_lens", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 4, + "w": 22, + "h": 23 + }, + "frame": { + "x": 154, + "y": 237, + "w": 22, + "h": 23 + } + }, + { + "filename": "dire_hit", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 133, + "y": 260, + "w": 22, + "h": 22 + } + }, + { + "filename": "dna_splicers", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 133, + "y": 282, + "w": 22, + "h": 22 + } + }, + { + "filename": "dragon_memory", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 155, + "y": 260, + "w": 22, + "h": 22 + } + }, + { + "filename": "electirizer", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 155, + "y": 282, + "w": 22, + "h": 22 + } + }, + { + "filename": "electric_memory", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 193, + "y": 132, + "w": 22, + "h": 22 + } + }, + { + "filename": "fairy_feather", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 22, + "h": 20 + }, + "frame": { + "x": 193, + "y": 154, + "w": 22, + "h": 20 + } + }, + { + "filename": "enigma_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 194, + "y": 174, + "w": 22, + "h": 22 + } + }, + { + "filename": "epic_egg", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 20, + "h": 22 + }, + "frame": { + "x": 175, + "y": 197, + "w": 20, + "h": 22 } }, { @@ -4161,8 +4014,8 @@ "h": 22 }, "frame": { - "x": 222, - "y": 129, + "x": 195, + "y": 196, "w": 22, "h": 22 } @@ -4182,8 +4035,8 @@ "h": 22 }, "frame": { - "x": 244, - "y": 130, + "x": 134, + "y": 304, "w": 22, "h": 22 } @@ -4203,8 +4056,8 @@ "h": 22 }, "frame": { - "x": 266, - "y": 130, + "x": 134, + "y": 326, "w": 22, "h": 22 } @@ -4224,8 +4077,8 @@ "h": 22 }, "frame": { - "x": 288, - "y": 131, + "x": 156, + "y": 304, "w": 22, "h": 22 } @@ -4245,12 +4098,33 @@ "h": 22 }, "frame": { - "x": 310, - "y": 131, + "x": 156, + "y": 326, "w": 22, "h": 22 } }, + { + "filename": "masterpiece_teacup", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 21, + "h": 18 + }, + "frame": { + "x": 175, + "y": 219, + "w": 21, + "h": 18 + } + }, { "filename": "ghost_memory", "rotated": false, @@ -4266,8 +4140,8 @@ "h": 22 }, "frame": { - "x": 332, - "y": 132, + "x": 176, + "y": 237, "w": 22, "h": 22 } @@ -4287,8 +4161,8 @@ "h": 22 }, "frame": { - "x": 354, - "y": 132, + "x": 177, + "y": 259, "w": 22, "h": 22 } @@ -4308,8 +4182,8 @@ "h": 22 }, "frame": { - "x": 376, - "y": 132, + "x": 177, + "y": 281, "w": 22, "h": 22 } @@ -4329,159 +4203,12 @@ "h": 22 }, "frame": { - "x": 398, - "y": 132, + "x": 178, + "y": 303, "w": 22, "h": 22 } }, - { - "filename": "relic_crown", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 7, - "w": 23, - "h": 18 - }, - "frame": { - "x": 140, - "y": 143, - "w": 23, - "h": 18 - } - }, - { - "filename": "max_repel", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 143, - "y": 161, - "w": 16, - "h": 24 - } - }, - { - "filename": "apicot_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 19, - "h": 20 - }, - "frame": { - "x": 146, - "y": 185, - "w": 19, - "h": 20 - } - }, - { - "filename": "hard_meteorite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 20, - "h": 22 - }, - "frame": { - "x": 154, - "y": 205, - "w": 20, - "h": 22 - } - }, - { - "filename": "sachet", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 4, - "w": 18, - "h": 23 - }, - "frame": { - "x": 156, - "y": 227, - "w": 18, - "h": 23 - } - }, - { - "filename": "hyper_potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 17, - "h": 23 - }, - "frame": { - "x": 157, - "y": 250, - "w": 17, - "h": 23 - } - }, - { - "filename": "pp_max", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 158, - "y": 273, - "w": 16, - "h": 24 - } - }, { "filename": "ice_memory", "rotated": false, @@ -4497,12 +4224,54 @@ "h": 22 }, "frame": { - "x": 158, - "y": 297, + "x": 178, + "y": 325, "w": 22, "h": 22 } }, + { + "filename": "blunder_policy", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 19 + }, + "frame": { + "x": 196, + "y": 218, + "w": 22, + "h": 19 + } + }, + { + "filename": "hard_meteorite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 20, + "h": 22 + }, + "frame": { + "x": 198, + "y": 237, + "w": 20, + "h": 22 + } + }, { "filename": "ice_stone", "rotated": false, @@ -4518,8 +4287,8 @@ "h": 22 }, "frame": { - "x": 159, - "y": 319, + "x": 199, + "y": 259, "w": 22, "h": 22 } @@ -4539,8 +4308,8 @@ "h": 22 }, "frame": { - "x": 160, - "y": 341, + "x": 199, + "y": 281, "w": 22, "h": 22 } @@ -4560,8 +4329,8 @@ "h": 22 }, "frame": { - "x": 160, - "y": 363, + "x": 200, + "y": 303, "w": 22, "h": 22 } @@ -4581,12 +4350,33 @@ "h": 22 }, "frame": { - "x": 162, - "y": 385, + "x": 200, + "y": 325, "w": 22, "h": 22 } }, + { + "filename": "shell_bell", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 23, + "h": 20 + }, + "frame": { + "x": 219, + "y": 112, + "w": 23, + "h": 20 + } + }, { "filename": "normal_memory", "rotated": false, @@ -4602,14 +4392,14 @@ "h": 22 }, "frame": { - "x": 163, - "y": 407, + "x": 215, + "y": 132, "w": 22, "h": 22 } }, { - "filename": "pp_up", + "filename": "malicious_armor", "rotated": false, "trimmed": true, "sourceSize": { @@ -4617,186 +4407,18 @@ "h": 32 }, "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 159, - "y": 161, - "w": 16, - "h": 24 - } - }, - { - "filename": "candy_jar", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, + "x": 5, "y": 6, - "w": 19, + "w": 22, "h": 20 }, "frame": { - "x": 165, - "y": 185, - "w": 19, + "x": 215, + "y": 154, + "w": 22, "h": 20 } }, - { - "filename": "protein", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 174, - "y": 205, - "w": 16, - "h": 24 - } - }, - { - "filename": "repel", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 174, - "y": 229, - "w": 16, - "h": 24 - } - }, - { - "filename": "super_repel", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 174, - "y": 253, - "w": 16, - "h": 24 - } - }, - { - "filename": "gb", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 20, - "h": 20 - }, - "frame": { - "x": 174, - "y": 277, - "w": 20, - "h": 20 - } - }, - { - "filename": "leftovers", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 15, - "h": 22 - }, - "frame": { - "x": 180, - "y": 297, - "w": 15, - "h": 22 - } - }, - { - "filename": "lock_capsule", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 19, - "h": 22 - }, - "frame": { - "x": 181, - "y": 319, - "w": 19, - "h": 22 - } - }, - { - "filename": "metal_coat", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 19, - "h": 22 - }, - "frame": { - "x": 182, - "y": 341, - "w": 19, - "h": 22 - } - }, { "filename": "poison_memory", "rotated": false, @@ -4812,8 +4434,8 @@ "h": 22 }, "frame": { - "x": 182, - "y": 363, + "x": 216, + "y": 174, "w": 22, "h": 22 } @@ -4833,8 +4455,8 @@ "h": 22 }, "frame": { - "x": 184, - "y": 385, + "x": 217, + "y": 196, "w": 22, "h": 22 } @@ -4854,77 +4476,14 @@ "h": 22 }, "frame": { - "x": 185, - "y": 407, + "x": 218, + "y": 218, "w": 22, "h": 22 } }, { - "filename": "relic_band", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 9, - "w": 17, - "h": 16 - }, - "frame": { - "x": 163, - "y": 145, - "w": 17, - "h": 16 - } - }, - { - "filename": "unknown", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 175, - "y": 161, - "w": 16, - "h": 24 - } - }, - { - "filename": "abomasite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 180, - "y": 145, - "w": 16, - "h": 16 - } - }, - { - "filename": "douse_drive", + "filename": "coupon", "rotated": false, "trimmed": true, "sourceSize": { @@ -4933,19 +4492,19 @@ }, "spriteSourceSize": { "x": 4, - "y": 8, + "y": 7, "w": 23, - "h": 17 + "h": 19 }, "frame": { - "x": 196, - "y": 147, + "x": 218, + "y": 240, "w": 23, - "h": 17 + "h": 19 } }, { - "filename": "liechi_berry", + "filename": "wellspring_mask", "rotated": false, "trimmed": true, "sourceSize": { @@ -4953,20 +4512,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, + "x": 4, + "y": 5, + "w": 23, "h": 21 }, "frame": { - "x": 191, - "y": 164, - "w": 22, + "x": 242, + "y": 112, + "w": 23, "h": 21 } }, { - "filename": "malicious_armor", + "filename": "legendary_egg", "rotated": false, "trimmed": true, "sourceSize": { @@ -4974,99 +4533,57 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 20 - }, - "frame": { - "x": 184, - "y": 185, - "w": 22, - "h": 20 - } - }, - { - "filename": "zinc", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 4, - "w": 16, - "h": 24 - }, - "frame": { - "x": 190, - "y": 205, - "w": 16, - "h": 24 - } - }, - { - "filename": "potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, + "x": 6, "y": 5, - "w": 17, - "h": 23 - }, - "frame": { - "x": 190, - "y": 229, - "w": 17, - "h": 23 - } - }, - { - "filename": "super_potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 17, - "h": 23 - }, - "frame": { - "x": 190, - "y": 252, - "w": 17, - "h": 23 - } - }, - { - "filename": "metronome", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 5, - "w": 17, + "w": 20, "h": 22 }, "frame": { - "x": 194, - "y": 275, - "w": 17, + "x": 221, + "y": 259, + "w": 20, + "h": 22 + } + }, + { + "filename": "rare_egg", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 20, + "h": 22 + }, + "frame": { + "x": 221, + "y": 281, + "w": 20, + "h": 22 + } + }, + { + "filename": "metal_coat", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 5, + "w": 19, + "h": 22 + }, + "frame": { + "x": 222, + "y": 303, + "w": 19, "h": 22 } }, @@ -5085,8 +4602,8 @@ "h": 22 }, "frame": { - "x": 195, - "y": 297, + "x": 222, + "y": 325, "w": 22, "h": 22 } @@ -5106,12 +4623,33 @@ "h": 22 }, "frame": { - "x": 200, - "y": 319, + "x": 237, + "y": 133, "w": 22, "h": 22 } }, + { + "filename": "dubious_disc", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 22, + "h": 19 + }, + "frame": { + "x": 237, + "y": 155, + "w": 22, + "h": 19 + } + }, { "filename": "scroll_of_waters", "rotated": false, @@ -5127,8 +4665,8 @@ "h": 22 }, "frame": { - "x": 201, - "y": 341, + "x": 238, + "y": 174, "w": 22, "h": 22 } @@ -5148,33 +4686,12 @@ "h": 22 }, "frame": { - "x": 204, - "y": 363, + "x": 239, + "y": 196, "w": 22, "h": 22 } }, - { - "filename": "sitrus_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 5, - "w": 20, - "h": 22 - }, - "frame": { - "x": 206, - "y": 385, - "w": 20, - "h": 22 - } - }, { "filename": "starf_berry", "rotated": false, @@ -5190,54 +4707,12 @@ "h": 22 }, "frame": { - "x": 207, - "y": 407, + "x": 240, + "y": 218, "w": 22, "h": 22 } }, - { - "filename": "shock_drive", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 23, - "h": 17 - }, - "frame": { - "x": 219, - "y": 151, - "w": 23, - "h": 17 - } - }, - { - "filename": "wise_glasses", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 4, - "y": 8, - "w": 23, - "h": 17 - }, - "frame": { - "x": 242, - "y": 152, - "w": 23, - "h": 17 - } - }, { "filename": "steel_memory", "rotated": false, @@ -5253,8 +4728,8 @@ "h": 22 }, "frame": { - "x": 265, - "y": 152, + "x": 241, + "y": 240, "w": 22, "h": 22 } @@ -5274,8 +4749,8 @@ "h": 22 }, "frame": { - "x": 287, - "y": 153, + "x": 241, + "y": 262, "w": 22, "h": 22 } @@ -5295,14 +4770,14 @@ "h": 22 }, "frame": { - "x": 309, - "y": 153, + "x": 241, + "y": 284, "w": 22, "h": 22 } }, { - "filename": "sweet_apple", + "filename": "golden_mystic_ticket", "rotated": false, "trimmed": true, "sourceSize": { @@ -5310,20 +4785,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 21 + "x": 4, + "y": 7, + "w": 23, + "h": 19 }, "frame": { - "x": 331, - "y": 154, - "w": 22, - "h": 21 + "x": 241, + "y": 306, + "w": 23, + "h": 19 } }, { - "filename": "syrupy_apple", + "filename": "rogue_egg", "rotated": false, "trimmed": true, "sourceSize": { @@ -5331,20 +4806,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 21 + "x": 6, + "y": 5, + "w": 20, + "h": 22 }, "frame": { - "x": 353, - "y": 154, - "w": 22, - "h": 21 + "x": 244, + "y": 325, + "w": 20, + "h": 22 } }, { - "filename": "tart_apple", + "filename": "deep_sea_tooth", "rotated": false, "trimmed": true, "sourceSize": { @@ -5358,8 +4833,8 @@ "h": 21 }, "frame": { - "x": 375, - "y": 154, + "x": 265, + "y": 112, "w": 22, "h": 21 } @@ -5379,33 +4854,12 @@ "h": 22 }, "frame": { - "x": 397, - "y": 154, + "x": 259, + "y": 133, "w": 22, "h": 22 } }, - { - "filename": "tera_orb", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 6, - "w": 22, - "h": 20 - }, - "frame": { - "x": 213, - "y": 168, - "w": 22, - "h": 20 - } - }, { "filename": "tm_bug", "rotated": false, @@ -5421,33 +4875,12 @@ "h": 22 }, "frame": { - "x": 206, - "y": 188, + "x": 287, + "y": 111, "w": 22, "h": 22 } }, - { - "filename": "upgrade", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 22, - "h": 19 - }, - "frame": { - "x": 206, - "y": 210, - "w": 22, - "h": 19 - } - }, { "filename": "tm_dark", "rotated": false, @@ -5463,8 +4896,8 @@ "h": 22 }, "frame": { - "x": 207, - "y": 229, + "x": 281, + "y": 133, "w": 22, "h": 22 } @@ -5484,8 +4917,8 @@ "h": 22 }, "frame": { - "x": 207, - "y": 251, + "x": 309, + "y": 111, "w": 22, "h": 22 } @@ -5505,33 +4938,12 @@ "h": 22 }, "frame": { - "x": 211, - "y": 273, + "x": 303, + "y": 133, "w": 22, "h": 22 } }, - { - "filename": "soothe_bell", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 5, - "w": 17, - "h": 22 - }, - "frame": { - "x": 217, - "y": 295, - "w": 17, - "h": 22 - } - }, { "filename": "tm_fairy", "rotated": false, @@ -5547,8 +4959,8 @@ "h": 22 }, "frame": { - "x": 235, - "y": 169, + "x": 331, + "y": 111, "w": 22, "h": 22 } @@ -5568,33 +4980,12 @@ "h": 22 }, "frame": { - "x": 228, - "y": 191, + "x": 325, + "y": 133, "w": 22, "h": 22 } }, - { - "filename": "absolite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 228, - "y": 213, - "w": 16, - "h": 16 - } - }, { "filename": "tm_fire", "rotated": false, @@ -5610,8 +5001,8 @@ "h": 22 }, "frame": { - "x": 229, - "y": 229, + "x": 353, + "y": 111, "w": 22, "h": 22 } @@ -5631,8 +5022,8 @@ "h": 22 }, "frame": { - "x": 229, - "y": 251, + "x": 347, + "y": 133, "w": 22, "h": 22 } @@ -5652,8 +5043,8 @@ "h": 22 }, "frame": { - "x": 233, - "y": 273, + "x": 375, + "y": 111, "w": 22, "h": 22 } @@ -5673,8 +5064,8 @@ "h": 22 }, "frame": { - "x": 234, - "y": 295, + "x": 369, + "y": 133, "w": 22, "h": 22 } @@ -5694,12 +5085,33 @@ "h": 22 }, "frame": { - "x": 222, - "y": 317, + "x": 397, + "y": 111, "w": 22, "h": 22 } }, + { + "filename": "pp_up", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 16, + "h": 24 + }, + "frame": { + "x": 419, + "y": 111, + "w": 16, + "h": 24 + } + }, { "filename": "tm_ice", "rotated": false, @@ -5715,8 +5127,8 @@ "h": 22 }, "frame": { - "x": 223, - "y": 339, + "x": 391, + "y": 133, "w": 22, "h": 22 } @@ -5736,12 +5148,33 @@ "h": 22 }, "frame": { - "x": 226, - "y": 361, + "x": 413, + "y": 135, "w": 22, "h": 22 } }, + { + "filename": "mystic_ticket", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 7, + "w": 23, + "h": 19 + }, + "frame": { + "x": 259, + "y": 155, + "w": 23, + "h": 19 + } + }, { "filename": "tm_poison", "rotated": false, @@ -5757,8 +5190,8 @@ "h": 22 }, "frame": { - "x": 226, - "y": 383, + "x": 260, + "y": 174, "w": 22, "h": 22 } @@ -5778,8 +5211,8 @@ "h": 22 }, "frame": { - "x": 229, - "y": 405, + "x": 282, + "y": 155, "w": 22, "h": 22 } @@ -5799,8 +5232,8 @@ "h": 22 }, "frame": { - "x": 244, - "y": 317, + "x": 261, + "y": 196, "w": 22, "h": 22 } @@ -5820,8 +5253,8 @@ "h": 22 }, "frame": { - "x": 245, - "y": 339, + "x": 304, + "y": 155, "w": 22, "h": 22 } @@ -5841,8 +5274,8 @@ "h": 22 }, "frame": { - "x": 248, - "y": 361, + "x": 262, + "y": 218, "w": 22, "h": 22 } @@ -5862,8 +5295,8 @@ "h": 22 }, "frame": { - "x": 248, - "y": 383, + "x": 326, + "y": 155, "w": 22, "h": 22 } @@ -5883,54 +5316,12 @@ "h": 22 }, "frame": { - "x": 251, - "y": 405, + "x": 348, + "y": 155, "w": 22, "h": 22 } }, - { - "filename": "eviolite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 15, - "h": 15 - }, - "frame": { - "x": 419, - "y": 154, - "w": 15, - "h": 15 - } - }, - { - "filename": "prism_scale", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 9, - "y": 8, - "w": 15, - "h": 15 - }, - "frame": { - "x": 419, - "y": 169, - "w": 15, - "h": 15 - } - }, { "filename": "x_accuracy", "rotated": false, @@ -5946,113 +5337,8 @@ "h": 22 }, "frame": { - "x": 257, - "y": 174, - "w": 22, - "h": 22 - } - }, - { - "filename": "x_attack", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 279, - "y": 175, - "w": 22, - "h": 22 - } - }, - { - "filename": "x_defense", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 301, - "y": 175, - "w": 22, - "h": 22 - } - }, - { - "filename": "x_sp_atk", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 323, - "y": 175, - "w": 22, - "h": 22 - } - }, - { - "filename": "x_sp_def", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 345, - "y": 175, - "w": 22, - "h": 22 - } - }, - { - "filename": "x_speed", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 5, - "w": 22, - "h": 22 - }, - "frame": { - "x": 367, - "y": 175, + "x": 370, + "y": 155, "w": 22, "h": 22 } @@ -6072,14 +5358,14 @@ "h": 21 }, "frame": { - "x": 389, - "y": 176, + "x": 392, + "y": 155, "w": 21, "h": 21 } }, { - "filename": "masterpiece_teacup", + "filename": "x_attack", "rotated": false, "trimmed": true, "sourceSize": { @@ -6088,19 +5374,145 @@ }, "spriteSourceSize": { "x": 5, - "y": 7, - "w": 21, - "h": 18 + "y": 5, + "w": 22, + "h": 22 }, "frame": { - "x": 250, - "y": 196, - "w": 21, - "h": 18 + "x": 413, + "y": 157, + "w": 22, + "h": 22 } }, { - "filename": "metal_alloy", + "filename": "pair_of_tickets", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 7, + "w": 23, + "h": 19 + }, + "frame": { + "x": 282, + "y": 177, + "w": 23, + "h": 19 + } + }, + { + "filename": "x_defense", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 283, + "y": 196, + "w": 22, + "h": 22 + } + }, + { + "filename": "x_sp_atk", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 305, + "y": 177, + "w": 22, + "h": 22 + } + }, + { + "filename": "x_sp_def", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 327, + "y": 177, + "w": 22, + "h": 22 + } + }, + { + "filename": "x_speed", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 5, + "w": 22, + "h": 22 + }, + "frame": { + "x": 349, + "y": 177, + "w": 22, + "h": 22 + } + }, + { + "filename": "liechi_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 21 + }, + "frame": { + "x": 263, + "y": 240, + "w": 22, + "h": 21 + } + }, + { + "filename": "sitrus_berry", "rotated": false, "trimmed": true, "sourceSize": { @@ -6109,15 +5521,57 @@ }, "spriteSourceSize": { "x": 6, - "y": 7, - "w": 21, - "h": 19 + "y": 5, + "w": 20, + "h": 22 }, "frame": { - "x": 271, - "y": 197, - "w": 21, - "h": 19 + "x": 284, + "y": 218, + "w": 20, + "h": 22 + } + }, + { + "filename": "sweet_apple", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 21 + }, + "frame": { + "x": 263, + "y": 261, + "w": 22, + "h": 21 + } + }, + { + "filename": "syrupy_apple", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 21 + }, + "frame": { + "x": 263, + "y": 282, + "w": 22, + "h": 21 } }, { @@ -6135,8 +5589,8 @@ "h": 21 }, "frame": { - "x": 292, - "y": 197, + "x": 371, + "y": 177, "w": 21, "h": 21 } @@ -6156,12 +5610,117 @@ "h": 21 }, "frame": { - "x": 313, - "y": 197, + "x": 392, + "y": 176, "w": 21, "h": 21 } }, + { + "filename": "tart_apple", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 6, + "w": 22, + "h": 21 + }, + "frame": { + "x": 413, + "y": 179, + "w": 22, + "h": 21 + } + }, + { + "filename": "relic_crown", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 7, + "w": 23, + "h": 18 + }, + "frame": { + "x": 305, + "y": 199, + "w": 23, + "h": 18 + } + }, + { + "filename": "sachet", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 4, + "w": 18, + "h": 23 + }, + "frame": { + "x": 285, + "y": 240, + "w": 18, + "h": 23 + } + }, + { + "filename": "chill_drive", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 23, + "h": 17 + }, + "frame": { + "x": 328, + "y": 199, + "w": 23, + "h": 17 + } + }, + { + "filename": "hyper_potion", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 17, + "h": 23 + }, + "frame": { + "x": 285, + "y": 263, + "w": 17, + "h": 23 + } + }, { "filename": "zoom_lens", "rotated": false, @@ -6177,14 +5736,14 @@ "h": 21 }, "frame": { - "x": 334, - "y": 197, + "x": 264, + "y": 303, "w": 21, "h": 21 } }, { - "filename": "dawn_stone", + "filename": "tera_orb", "rotated": false, "trimmed": true, "sourceSize": { @@ -6192,20 +5751,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 6, + "x": 5, "y": 6, - "w": 20, - "h": 21 + "w": 22, + "h": 20 }, "frame": { - "x": 355, - "y": 197, - "w": 20, - "h": 21 + "x": 264, + "y": 324, + "w": 22, + "h": 20 } }, { - "filename": "flying_tera_shard", + "filename": "potion", "rotated": false, "trimmed": true, "sourceSize": { @@ -6213,20 +5772,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, + "x": 8, "y": 5, - "w": 20, - "h": 21 + "w": 17, + "h": 23 }, "frame": { - "x": 375, - "y": 197, - "w": 20, - "h": 21 + "x": 285, + "y": 286, + "w": 17, + "h": 23 } }, { - "filename": "quick_claw", + "filename": "blue_orb", "rotated": false, "trimmed": true, "sourceSize": { @@ -6236,14 +5795,98 @@ "spriteSourceSize": { "x": 6, "y": 6, - "w": 19, - "h": 21 + "w": 20, + "h": 20 }, "frame": { - "x": 395, - "y": 197, - "w": 19, - "h": 21 + "x": 351, + "y": 199, + "w": 20, + "h": 20 + } + }, + { + "filename": "gb", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 20, + "h": 20 + }, + "frame": { + "x": 371, + "y": 198, + "w": 20, + "h": 20 + } + }, + { + "filename": "silver_powder", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 11, + "w": 24, + "h": 15 + }, + "frame": { + "x": 285, + "y": 309, + "w": 24, + "h": 15 + } + }, + { + "filename": "upgrade", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 22, + "h": 19 + }, + "frame": { + "x": 286, + "y": 324, + "w": 22, + "h": 19 + } + }, + { + "filename": "douse_drive", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 23, + "h": 17 + }, + "frame": { + "x": 134, + "y": 348, + "w": 23, + "h": 17 } }, { @@ -6261,12 +5904,33 @@ "h": 20 }, "frame": { - "x": 414, - "y": 184, + "x": 132, + "y": 365, "w": 20, "h": 20 } }, + { + "filename": "metal_alloy", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 21, + "h": 19 + }, + "frame": { + "x": 157, + "y": 348, + "w": 21, + "h": 19 + } + }, { "filename": "mb", "rotated": false, @@ -6282,8 +5946,8 @@ "h": 20 }, "frame": { - "x": 414, - "y": 204, + "x": 178, + "y": 347, "w": 20, "h": 20 } @@ -6303,33 +5967,12 @@ "h": 20 }, "frame": { - "x": 251, - "y": 214, + "x": 198, + "y": 347, "w": 20, "h": 20 } }, - { - "filename": "old_gateau", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 21, - "h": 18 - }, - "frame": { - "x": 271, - "y": 216, - "w": 21, - "h": 18 - } - }, { "filename": "pb_gold", "rotated": false, @@ -6345,33 +5988,12 @@ "h": 20 }, "frame": { - "x": 251, - "y": 234, + "x": 218, + "y": 347, "w": 20, "h": 20 } }, - { - "filename": "lum_berry", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 20, - "h": 19 - }, - "frame": { - "x": 251, - "y": 254, - "w": 20, - "h": 19 - } - }, { "filename": "pb_silver", "rotated": false, @@ -6387,12 +6009,180 @@ "h": 20 }, "frame": { - "x": 271, - "y": 234, + "x": 238, + "y": 347, "w": 20, "h": 20 } }, + { + "filename": "shock_drive", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 23, + "h": 17 + }, + "frame": { + "x": 152, + "y": 367, + "w": 23, + "h": 17 + } + }, + { + "filename": "wise_glasses", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 4, + "y": 8, + "w": 23, + "h": 17 + }, + "frame": { + "x": 175, + "y": 367, + "w": 23, + "h": 17 + } + }, + { + "filename": "old_gateau", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 21, + "h": 18 + }, + "frame": { + "x": 198, + "y": 367, + "w": 21, + "h": 18 + } + }, + { + "filename": "sharp_meteorite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 21, + "h": 18 + }, + "frame": { + "x": 219, + "y": 367, + "w": 21, + "h": 18 + } + }, + { + "filename": "baton", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 18 + }, + "frame": { + "x": 240, + "y": 367, + "w": 18, + "h": 18 + } + }, + { + "filename": "everstone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 17 + }, + "frame": { + "x": 132, + "y": 385, + "w": 20, + "h": 17 + } + }, + { + "filename": "unremarkable_teacup", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 5, + "y": 7, + "w": 21, + "h": 18 + }, + "frame": { + "x": 152, + "y": 384, + "w": 21, + "h": 18 + } + }, + { + "filename": "lum_berry", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 20, + "h": 19 + }, + "frame": { + "x": 173, + "y": 384, + "w": 20, + "h": 19 + } + }, { "filename": "power_herb", "rotated": false, @@ -6408,8 +6198,29 @@ "h": 19 }, "frame": { - "x": 271, - "y": 254, + "x": 193, + "y": 385, + "w": 20, + "h": 19 + } + }, + { + "filename": "razor_claw", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 20, + "h": 19 + }, + "frame": { + "x": 213, + "y": 385, "w": 20, "h": 19 } @@ -6429,14 +6240,14 @@ "h": 20 }, "frame": { - "x": 255, - "y": 273, + "x": 233, + "y": 385, "w": 20, "h": 20 } }, { - "filename": "spell_tag", + "filename": "protein", "rotated": false, "trimmed": true, "sourceSize": { @@ -6444,20 +6255,83 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 19, - "h": 21 + "x": 8, + "y": 4, + "w": 16, + "h": 24 }, "frame": { - "x": 256, - "y": 293, - "w": 19, - "h": 21 + "x": 258, + "y": 347, + "w": 16, + "h": 24 } }, { - "filename": "sharp_meteorite", + "filename": "repel", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 16, + "h": 24 + }, + "frame": { + "x": 274, + "y": 344, + "w": 16, + "h": 24 + } + }, + { + "filename": "super_potion", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 17, + "h": 23 + }, + "frame": { + "x": 290, + "y": 343, + "w": 17, + "h": 23 + } + }, + { + "filename": "abomasite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 258, + "y": 371, + "w": 16, + "h": 16 + } + }, + { + "filename": "big_mushroom", "rotated": false, "trimmed": true, "sourceSize": { @@ -6466,15 +6340,36 @@ }, "spriteSourceSize": { "x": 6, - "y": 8, - "w": 21, - "h": 18 + "y": 6, + "w": 19, + "h": 19 }, "frame": { - "x": 292, - "y": 218, - "w": 21, - "h": 18 + "x": 274, + "y": 368, + "w": 19, + "h": 19 + } + }, + { + "filename": "full_heal", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 9, + "y": 4, + "w": 15, + "h": 23 + }, + "frame": { + "x": 293, + "y": 366, + "w": 15, + "h": 23 } }, { @@ -6492,33 +6387,12 @@ "h": 20 }, "frame": { - "x": 291, - "y": 236, + "x": 253, + "y": 387, "w": 20, "h": 20 } }, - { - "filename": "unremarkable_teacup", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 5, - "y": 7, - "w": 21, - "h": 18 - }, - "frame": { - "x": 313, - "y": 218, - "w": 21, - "h": 18 - } - }, { "filename": "strange_ball", "rotated": false, @@ -6534,14 +6408,350 @@ "h": 20 }, "frame": { - "x": 311, - "y": 236, + "x": 273, + "y": 387, "w": 20, "h": 20 } }, { - "filename": "razor_claw", + "filename": "candy", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 11, + "w": 18, + "h": 18 + }, + "frame": { + "x": 293, + "y": 389, + "w": 18, + "h": 18 + } + }, + { + "filename": "super_repel", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 16, + "h": 24 + }, + "frame": { + "x": 302, + "y": 263, + "w": 16, + "h": 24 + } + }, + { + "filename": "metronome", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 5, + "w": 17, + "h": 22 + }, + "frame": { + "x": 302, + "y": 287, + "w": 17, + "h": 22 + } + }, + { + "filename": "absolite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 309, + "y": 309, + "w": 16, + "h": 16 + } + }, + { + "filename": "candy_jar", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 19, + "h": 20 + }, + "frame": { + "x": 308, + "y": 325, + "w": 19, + "h": 20 + } + }, + { + "filename": "quick_claw", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 19, + "h": 21 + }, + "frame": { + "x": 307, + "y": 345, + "w": 19, + "h": 21 + } + }, + { + "filename": "soothe_bell", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 17, + "h": 22 + }, + "frame": { + "x": 308, + "y": 366, + "w": 17, + "h": 22 + } + }, + { + "filename": "golden_egg", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 17, + "h": 20 + }, + "frame": { + "x": 311, + "y": 388, + "w": 17, + "h": 20 + } + }, + { + "filename": "leftovers", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 5, + "w": 15, + "h": 22 + }, + "frame": { + "x": 325, + "y": 366, + "w": 15, + "h": 22 + } + }, + { + "filename": "spell_tag", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 19, + "h": 21 + }, + "frame": { + "x": 326, + "y": 345, + "w": 19, + "h": 21 + } + }, + { + "filename": "hard_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 6, + "w": 19, + "h": 20 + }, + "frame": { + "x": 328, + "y": 388, + "w": 19, + "h": 20 + } + }, + { + "filename": "lucky_egg", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 17, + "h": 20 + }, + "frame": { + "x": 340, + "y": 366, + "w": 17, + "h": 20 + } + }, + { + "filename": "unknown", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 16, + "h": 24 + }, + "frame": { + "x": 347, + "y": 386, + "w": 16, + "h": 24 + } + }, + { + "filename": "mega_bracelet", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 16 + }, + "frame": { + "x": 67, + "y": 402, + "w": 20, + "h": 16 + } + }, + { + "filename": "revive", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 10, + "y": 8, + "w": 12, + "h": 17 + }, + "frame": { + "x": 65, + "y": 418, + "w": 12, + "h": 17 + } + }, + { + "filename": "aerodactylite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 77, + "y": 418, + "w": 16, + "h": 16 + } + }, + { + "filename": "white_herb", "rotated": false, "trimmed": true, "sourceSize": { @@ -6555,8 +6765,8 @@ "h": 19 }, "frame": { - "x": 334, - "y": 218, + "x": 88, + "y": 399, "w": 20, "h": 19 } @@ -6576,119 +6786,14 @@ "h": 20 }, "frame": { - "x": 354, - "y": 218, + "x": 108, + "y": 399, "w": 20, "h": 20 } }, { - "filename": "hard_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 19, - "h": 20 - }, - "frame": { - "x": 374, - "y": 218, - "w": 19, - "h": 20 - } - }, - { - "filename": "white_herb", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 20, - "h": 19 - }, - "frame": { - "x": 393, - "y": 218, - "w": 20, - "h": 19 - } - }, - { - "filename": "everstone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 17 - }, - "frame": { - "x": 291, - "y": 256, - "w": 20, - "h": 17 - } - }, - { - "filename": "big_mushroom", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 6, - "w": 19, - "h": 19 - }, - "frame": { - "x": 275, - "y": 273, - "w": 19, - "h": 19 - } - }, - { - "filename": "miracle_seed", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 7, - "w": 19, - "h": 19 - }, - "frame": { - "x": 275, - "y": 292, - "w": 19, - "h": 19 - } - }, - { - "filename": "golden_egg", + "filename": "relic_band", "rotated": false, "trimmed": true, "sourceSize": { @@ -6697,311 +6802,17 @@ }, "spriteSourceSize": { "x": 7, - "y": 6, + "y": 9, "w": 17, - "h": 20 - }, - "frame": { - "x": 294, - "y": 273, - "w": 17, - "h": 20 - } - }, - { - "filename": "razor_fang", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 18, - "h": 20 - }, - "frame": { - "x": 311, - "y": 256, - "w": 18, - "h": 20 - } - }, - { - "filename": "baton", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 18 - }, - "frame": { - "x": 294, - "y": 293, - "w": 18, - "h": 18 - } - }, - { - "filename": "wl_ability_urge", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 331, - "y": 237, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_antidote", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 351, - "y": 238, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_awakening", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 371, - "y": 238, - "w": 20, - "h": 18 - } - }, - { - "filename": "aerodactylite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, "h": 16 }, "frame": { - "x": 311, - "y": 276, - "w": 16, + "x": 93, + "y": 419, + "w": 17, "h": 16 } }, - { - "filename": "lucky_egg", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 6, - "w": 17, - "h": 20 - }, - "frame": { - "x": 312, - "y": 292, - "w": 17, - "h": 20 - } - }, - { - "filename": "wl_burn_heal", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 413, - "y": 224, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_custom_spliced", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 393, - "y": 237, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_custom_thief", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 413, - "y": 242, - "w": 20, - "h": 18 - } - }, - { - "filename": "oval_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 19 - }, - "frame": { - "x": 266, - "y": 314, - "w": 18, - "h": 19 - } - }, - { - "filename": "wl_elixir", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 284, - "y": 311, - "w": 20, - "h": 18 - } - }, - { - "filename": "candy", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 11, - "w": 18, - "h": 18 - }, - "frame": { - "x": 267, - "y": 333, - "w": 18, - "h": 18 - } - }, - { - "filename": "wl_ether", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 285, - "y": 329, - "w": 20, - "h": 18 - } - }, { "filename": "aggronite", "rotated": false, @@ -7017,33 +6828,12 @@ "h": 16 }, "frame": { - "x": 304, - "y": 312, + "x": 110, + "y": 419, "w": 16, "h": 16 } }, - { - "filename": "dark_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 18 - }, - "frame": { - "x": 305, - "y": 328, - "w": 18, - "h": 18 - } - }, { "filename": "alakazite", "rotated": false, @@ -7059,14 +6849,14 @@ "h": 16 }, "frame": { - "x": 320, - "y": 312, + "x": 126, + "y": 419, "w": 16, "h": 16 } }, { - "filename": "flame_orb", + "filename": "altarianite", "rotated": false, "trimmed": true, "sourceSize": { @@ -7074,20 +6864,20 @@ "h": 32 }, "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 18 + "x": 8, + "y": 8, + "w": 16, + "h": 16 }, "frame": { - "x": 323, - "y": 328, - "w": 18, - "h": 18 + "x": 128, + "y": 403, + "w": 16, + "h": 16 } }, { - "filename": "wl_full_heal", + "filename": "wl_ability_urge", "rotated": false, "trimmed": true, "sourceSize": { @@ -7101,14 +6891,119 @@ "h": 18 }, "frame": { - "x": 285, - "y": 347, + "x": 144, + "y": 402, "w": 20, "h": 18 } }, { - "filename": "wl_full_restore", + "filename": "candy_overlay", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 12, + "w": 16, + "h": 15 + }, + "frame": { + "x": 142, + "y": 420, + "w": 16, + "h": 15 + } + }, + { + "filename": "eviolite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 15, + "h": 15 + }, + "frame": { + "x": 158, + "y": 420, + "w": 15, + "h": 15 + } + }, + { + "filename": "ampharosite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 164, + "y": 404, + "w": 16, + "h": 16 + } + }, + { + "filename": "prism_scale", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 9, + "y": 8, + "w": 15, + "h": 15 + }, + "frame": { + "x": 173, + "y": 420, + "w": 15, + "h": 15 + } + }, + { + "filename": "audinite", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 8, + "w": 16, + "h": 16 + }, + "frame": { + "x": 180, + "y": 404, + "w": 16, + "h": 16 + } + }, + { + "filename": "wl_antidote", "rotated": false, "trimmed": true, "sourceSize": { @@ -7122,176 +7017,8 @@ "h": 18 }, "frame": { - "x": 305, - "y": 346, - "w": 20, - "h": 18 - } - }, - { - "filename": "light_ball", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 18 - }, - "frame": { - "x": 325, - "y": 346, - "w": 18, - "h": 18 - } - }, - { - "filename": "wl_guard_spec", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 270, - "y": 365, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_hyper_potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 270, - "y": 383, - "w": 20, - "h": 18 - } - }, - { - "filename": "light_stone", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 18 - }, - "frame": { - "x": 290, - "y": 365, - "w": 18, - "h": 18 - } - }, - { - "filename": "wl_ice_heal", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 308, - "y": 364, - "w": 20, - "h": 18 - } - }, - { - "filename": "toxic_orb", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 7, - "y": 7, - "w": 18, - "h": 18 - }, - "frame": { - "x": 290, - "y": 383, - "w": 18, - "h": 18 - } - }, - { - "filename": "wl_item_drop", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 308, - "y": 382, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_item_urge", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 273, - "y": 401, + "x": 196, + "y": 404, "w": 20, "h": 18 } @@ -7311,12 +7038,369 @@ "h": 18 }, "frame": { - "x": 328, - "y": 364, + "x": 216, + "y": 404, "w": 16, "h": 18 } }, + { + "filename": "wl_awakening", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 232, + "y": 405, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_burn_heal", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 252, + "y": 407, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_custom_spliced", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 272, + "y": 407, + "w": 20, + "h": 18 + } + }, + { + "filename": "miracle_seed", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 7, + "w": 19, + "h": 19 + }, + "frame": { + "x": 292, + "y": 407, + "w": 19, + "h": 19 + } + }, + { + "filename": "wl_custom_thief", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 311, + "y": 408, + "w": 20, + "h": 18 + } + }, + { + "filename": "zinc", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 8, + "y": 4, + "w": 16, + "h": 24 + }, + "frame": { + "x": 331, + "y": 408, + "w": 16, + "h": 24 + } + }, + { + "filename": "razor_fang", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 6, + "w": 18, + "h": 20 + }, + "frame": { + "x": 347, + "y": 410, + "w": 18, + "h": 20 + } + }, + { + "filename": "wl_elixir", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 392, + "y": 197, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_ether", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 412, + "y": 200, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_full_heal", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 391, + "y": 215, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_full_restore", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 371, + "y": 218, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_guard_spec", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 411, + "y": 218, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_hyper_potion", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 391, + "y": 233, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_ice_heal", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 411, + "y": 236, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_item_drop", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 305, + "y": 217, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_item_urge", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 304, + "y": 235, + "w": 20, + "h": 18 + } + }, + { + "filename": "dark_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 18 + }, + "frame": { + "x": 325, + "y": 217, + "w": 18, + "h": 18 + } + }, { "filename": "wl_max_elixir", "rotated": false, @@ -7332,8 +7416,8 @@ "h": 18 }, "frame": { - "x": 328, - "y": 382, + "x": 324, + "y": 235, "w": 20, "h": 18 } @@ -7353,218 +7437,8 @@ "h": 18 }, "frame": { - "x": 293, - "y": 401, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_max_potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 313, - "y": 400, - "w": 20, - "h": 18 - } - }, - { - "filename": "altarianite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 313, - "y": 418, - "w": 16, - "h": 16 - } - }, - { - "filename": "ampharosite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 329, - "y": 418, - "w": 16, - "h": 16 - } - }, - { - "filename": "wl_max_revive", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 333, - "y": 400, - "w": 20, - "h": 18 - } - }, - { - "filename": "audinite", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 8, - "y": 8, - "w": 16, - "h": 16 - }, - "frame": { - "x": 345, - "y": 418, - "w": 16, - "h": 16 - } - }, - { - "filename": "wl_paralyze_heal", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 331, - "y": 255, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 351, - "y": 256, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_reset_urge", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 371, - "y": 256, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_revive", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 391, - "y": 255, - "w": 20, - "h": 18 - } - }, - { - "filename": "wl_super_potion", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 32, - "h": 32 - }, - "spriteSourceSize": { - "x": 6, - "y": 8, - "w": 20, - "h": 18 - }, - "frame": { - "x": 411, - "y": 260, + "x": 318, + "y": 253, "w": 20, "h": 18 } @@ -7584,12 +7458,75 @@ "h": 16 }, "frame": { - "x": 327, - "y": 276, + "x": 318, + "y": 271, "w": 16, "h": 16 } }, + { + "filename": "oval_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 19 + }, + "frame": { + "x": 319, + "y": 287, + "w": 18, + "h": 19 + } + }, + { + "filename": "flame_orb", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 18 + }, + "frame": { + "x": 325, + "y": 306, + "w": 18, + "h": 18 + } + }, + { + "filename": "light_ball", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 18 + }, + "frame": { + "x": 327, + "y": 324, + "w": 18, + "h": 18 + } + }, { "filename": "beedrillite", "rotated": false, @@ -7605,12 +7542,54 @@ "h": 16 }, "frame": { - "x": 329, - "y": 292, + "x": 343, + "y": 219, "w": 16, "h": 16 } }, + { + "filename": "light_stone", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 18 + }, + "frame": { + "x": 344, + "y": 235, + "w": 18, + "h": 18 + } + }, + { + "filename": "wl_max_potion", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 338, + "y": 253, + "w": 20, + "h": 18 + } + }, { "filename": "blastoisinite", "rotated": false, @@ -7626,12 +7605,33 @@ "h": 16 }, "frame": { - "x": 343, - "y": 274, + "x": 334, + "y": 271, "w": 16, "h": 16 } }, + { + "filename": "toxic_orb", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 7, + "y": 7, + "w": 18, + "h": 18 + }, + "frame": { + "x": 337, + "y": 287, + "w": 18, + "h": 18 + } + }, { "filename": "blazikenite", "rotated": false, @@ -7647,12 +7647,75 @@ "h": 16 }, "frame": { - "x": 359, - "y": 274, + "x": 350, + "y": 271, "w": 16, "h": 16 } }, + { + "filename": "wl_max_revive", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 358, + "y": 253, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_paralyze_heal", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 343, + "y": 305, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_potion", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 355, + "y": 287, + "w": 20, + "h": 18 + } + }, { "filename": "cameruptite", "rotated": false, @@ -7668,12 +7731,75 @@ "h": 16 }, "frame": { - "x": 375, - "y": 274, + "x": 366, + "y": 271, "w": 16, "h": 16 } }, + { + "filename": "wl_reset_urge", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 345, + "y": 323, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_revive", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 345, + "y": 341, + "w": 20, + "h": 18 + } + }, + { + "filename": "wl_super_potion", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 6, + "y": 8, + "w": 20, + "h": 18 + }, + "frame": { + "x": 363, + "y": 305, + "w": 20, + "h": 18 + } + }, { "filename": "charizardite_x", "rotated": false, @@ -7689,8 +7815,8 @@ "h": 16 }, "frame": { - "x": 391, - "y": 273, + "x": 365, + "y": 323, "w": 16, "h": 16 } @@ -7710,8 +7836,8 @@ "h": 16 }, "frame": { - "x": 345, - "y": 290, + "x": 365, + "y": 339, "w": 16, "h": 16 } @@ -7731,8 +7857,8 @@ "h": 16 }, "frame": { - "x": 361, - "y": 290, + "x": 362, + "y": 236, "w": 16, "h": 16 } @@ -7752,8 +7878,8 @@ "h": 16 }, "frame": { - "x": 377, - "y": 290, + "x": 375, + "y": 287, "w": 16, "h": 16 } @@ -7773,8 +7899,8 @@ "h": 16 }, "frame": { - "x": 393, - "y": 289, + "x": 383, + "y": 303, "w": 16, "h": 16 } @@ -7794,8 +7920,8 @@ "h": 16 }, "frame": { - "x": 336, - "y": 308, + "x": 365, + "y": 355, "w": 16, "h": 16 } @@ -7815,8 +7941,8 @@ "h": 16 }, "frame": { - "x": 352, - "y": 306, + "x": 383, + "y": 319, "w": 16, "h": 16 } @@ -7836,8 +7962,8 @@ "h": 16 }, "frame": { - "x": 368, - "y": 306, + "x": 381, + "y": 335, "w": 16, "h": 16 } @@ -7857,8 +7983,8 @@ "h": 16 }, "frame": { - "x": 384, - "y": 306, + "x": 381, + "y": 351, "w": 16, "h": 16 } @@ -7878,8 +8004,8 @@ "h": 16 }, "frame": { - "x": 400, - "y": 305, + "x": 381, + "y": 367, "w": 16, "h": 16 } @@ -7899,8 +8025,8 @@ "h": 16 }, "frame": { - "x": 341, - "y": 324, + "x": 365, + "y": 371, "w": 16, "h": 16 } @@ -7920,8 +8046,8 @@ "h": 16 }, "frame": { - "x": 357, - "y": 322, + "x": 363, + "y": 387, "w": 16, "h": 16 } @@ -7941,8 +8067,8 @@ "h": 16 }, "frame": { - "x": 373, - "y": 322, + "x": 365, + "y": 403, "w": 16, "h": 16 } @@ -7962,8 +8088,8 @@ "h": 16 }, "frame": { - "x": 389, - "y": 322, + "x": 365, + "y": 419, "w": 16, "h": 16 } @@ -7983,8 +8109,8 @@ "h": 16 }, "frame": { - "x": 405, - "y": 321, + "x": 381, + "y": 383, "w": 16, "h": 16 } @@ -8004,8 +8130,8 @@ "h": 16 }, "frame": { - "x": 343, - "y": 340, + "x": 381, + "y": 399, "w": 16, "h": 16 } @@ -8025,8 +8151,8 @@ "h": 16 }, "frame": { - "x": 359, - "y": 338, + "x": 381, + "y": 415, "w": 16, "h": 16 } @@ -8046,8 +8172,8 @@ "h": 16 }, "frame": { - "x": 375, - "y": 338, + "x": 378, + "y": 251, "w": 16, "h": 16 } @@ -8067,8 +8193,8 @@ "h": 16 }, "frame": { - "x": 391, - "y": 338, + "x": 394, + "y": 251, "w": 16, "h": 16 } @@ -8088,8 +8214,8 @@ "h": 16 }, "frame": { - "x": 407, - "y": 337, + "x": 382, + "y": 267, "w": 16, "h": 16 } @@ -8109,8 +8235,8 @@ "h": 16 }, "frame": { - "x": 344, - "y": 356, + "x": 410, + "y": 254, "w": 16, "h": 16 } @@ -8130,8 +8256,8 @@ "h": 16 }, "frame": { - "x": 360, - "y": 354, + "x": 391, + "y": 283, "w": 16, "h": 16 } @@ -8151,8 +8277,8 @@ "h": 16 }, "frame": { - "x": 376, - "y": 354, + "x": 399, + "y": 299, "w": 16, "h": 16 } @@ -8172,8 +8298,8 @@ "h": 16 }, "frame": { - "x": 392, - "y": 354, + "x": 399, + "y": 315, "w": 16, "h": 16 } @@ -8193,8 +8319,8 @@ "h": 16 }, "frame": { - "x": 408, - "y": 353, + "x": 399, + "y": 331, "w": 16, "h": 16 } @@ -8214,8 +8340,8 @@ "h": 16 }, "frame": { - "x": 409, - "y": 278, + "x": 397, + "y": 347, "w": 16, "h": 16 } @@ -8235,8 +8361,8 @@ "h": 16 }, "frame": { - "x": 348, - "y": 372, + "x": 397, + "y": 363, "w": 16, "h": 16 } @@ -8256,8 +8382,8 @@ "h": 16 }, "frame": { - "x": 364, - "y": 370, + "x": 397, + "y": 379, "w": 16, "h": 16 } @@ -8277,8 +8403,8 @@ "h": 16 }, "frame": { - "x": 380, - "y": 370, + "x": 397, + "y": 395, "w": 16, "h": 16 } @@ -8298,12 +8424,33 @@ "h": 16 }, "frame": { - "x": 396, - "y": 370, + "x": 397, + "y": 411, "w": 16, "h": 16 } }, + { + "filename": "relic_gold", + "rotated": false, + "trimmed": true, + "sourceSize": { + "w": 32, + "h": 32 + }, + "spriteSourceSize": { + "x": 9, + "y": 11, + "w": 15, + "h": 11 + }, + "frame": { + "x": 188, + "y": 422, + "w": 15, + "h": 11 + } + }, { "filename": "sharpedonite", "rotated": false, @@ -8319,8 +8466,8 @@ "h": 16 }, "frame": { - "x": 412, - "y": 369, + "x": 413, + "y": 347, "w": 16, "h": 16 } @@ -8340,8 +8487,8 @@ "h": 16 }, "frame": { - "x": 364, - "y": 386, + "x": 413, + "y": 363, "w": 16, "h": 16 } @@ -8361,8 +8508,8 @@ "h": 16 }, "frame": { - "x": 380, - "y": 386, + "x": 413, + "y": 379, "w": 16, "h": 16 } @@ -8382,8 +8529,8 @@ "h": 16 }, "frame": { - "x": 396, - "y": 386, + "x": 413, + "y": 395, "w": 16, "h": 16 } @@ -8403,8 +8550,8 @@ "h": 16 }, "frame": { - "x": 412, - "y": 385, + "x": 413, + "y": 411, "w": 16, "h": 16 } @@ -8424,8 +8571,8 @@ "h": 16 }, "frame": { - "x": 353, - "y": 402, + "x": 407, + "y": 270, "w": 16, "h": 16 } @@ -8445,8 +8592,8 @@ "h": 16 }, "frame": { - "x": 361, - "y": 418, + "x": 415, + "y": 286, "w": 16, "h": 16 } @@ -8466,8 +8613,8 @@ "h": 16 }, "frame": { - "x": 369, - "y": 402, + "x": 415, + "y": 302, "w": 16, "h": 16 } @@ -8478,6 +8625,6 @@ "meta": { "app": "https://www.codeandweb.com/texturepacker", "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:9b6fc7b241128f4f61686fe287e090cd:46e9caafcc91f3c30ff85a6e8d3f5227:110e074689c9edd2c54833ce2e4d9270$" + "smartupdate": "$TexturePacker:SmartUpdate:f593140f9e137ba20f8bcb629ad2d6dc:5a2e6eb481a58dab37c12113287770c0:110e074689c9edd2c54833ce2e4d9270$" } } diff --git a/public/images/items.png b/public/images/items.png index f0f11e9443e..a4ca454a153 100644 Binary files a/public/images/items.png and b/public/images/items.png differ diff --git a/public/images/items/ampharosite.png b/public/images/items/ampharosite.png index 154f7ea5609..3297b4a90b8 100644 Binary files a/public/images/items/ampharosite.png and b/public/images/items/ampharosite.png differ diff --git a/public/images/items/amulet_coin.png b/public/images/items/amulet_coin.png index 727562836c4..8c86df496e4 100644 Binary files a/public/images/items/amulet_coin.png and b/public/images/items/amulet_coin.png differ diff --git a/public/images/items/blunder_policy.png b/public/images/items/blunder_policy.png index 8104d00c40c..ba7b12ebaab 100644 Binary files a/public/images/items/blunder_policy.png and b/public/images/items/blunder_policy.png differ diff --git a/public/images/items/bronze_ribbon.png b/public/images/items/bronze_ribbon.png deleted file mode 100644 index 13eeb7254ca..00000000000 Binary files a/public/images/items/bronze_ribbon.png and /dev/null differ diff --git a/public/images/items/bug_memory.png b/public/images/items/bug_memory.png index a71637ceb5a..fce22e69081 100644 Binary files a/public/images/items/bug_memory.png and b/public/images/items/bug_memory.png differ diff --git a/public/images/items/calendar.png b/public/images/items/calendar.png new file mode 100644 index 00000000000..4d891a856c3 Binary files /dev/null and b/public/images/items/calendar.png differ diff --git a/public/images/items/catching_charm.png b/public/images/items/catching_charm.png index 4699b8c3d85..8fd89791206 100644 Binary files a/public/images/items/catching_charm.png and b/public/images/items/catching_charm.png differ diff --git a/public/images/items/common_egg.png b/public/images/items/common_egg.png new file mode 100644 index 00000000000..5eccff2f690 Binary files /dev/null and b/public/images/items/common_egg.png differ diff --git a/public/images/items/common_ribbon.png b/public/images/items/common_ribbon.png new file mode 100644 index 00000000000..965527d747b Binary files /dev/null and b/public/images/items/common_ribbon.png differ diff --git a/public/images/items/diancite.png b/public/images/items/diancite.png index fbb0267fb59..3c871b3158b 100644 Binary files a/public/images/items/diancite.png and b/public/images/items/diancite.png differ diff --git a/public/images/items/epic_egg.png b/public/images/items/epic_egg.png new file mode 100644 index 00000000000..96950e27978 Binary files /dev/null and b/public/images/items/epic_egg.png differ diff --git a/public/images/items/flying_tera_shard.png b/public/images/items/flying_tera_shard.png index 42e2b16c4d2..7cecc5d0945 100644 Binary files a/public/images/items/flying_tera_shard.png and b/public/images/items/flying_tera_shard.png differ diff --git a/public/images/items/galarica_cuff.png b/public/images/items/galarica_cuff.png index 4706279c43d..223be91acee 100644 Binary files a/public/images/items/galarica_cuff.png and b/public/images/items/galarica_cuff.png differ diff --git a/public/images/items/gardevoirite.png b/public/images/items/gardevoirite.png index 9180b369df4..5f5d75f7ca5 100644 Binary files a/public/images/items/gardevoirite.png and b/public/images/items/gardevoirite.png differ diff --git a/public/images/items/gb.png b/public/images/items/gb.png index bcc88593fad..3a47a5cd3ce 100644 Binary files a/public/images/items/gb.png and b/public/images/items/gb.png differ diff --git a/public/images/items/great_ribbon.png b/public/images/items/great_ribbon.png index e246d8db981..4db20f29c1f 100644 Binary files a/public/images/items/great_ribbon.png and b/public/images/items/great_ribbon.png differ diff --git a/public/images/items/hp_up.png b/public/images/items/hp_up.png index b9284383978..ddbca745436 100644 Binary files a/public/images/items/hp_up.png and b/public/images/items/hp_up.png differ diff --git a/public/images/items/leftovers.png b/public/images/items/leftovers.png index c06eaf073d9..43200bfe559 100644 Binary files a/public/images/items/leftovers.png and b/public/images/items/leftovers.png differ diff --git a/public/images/items/legendary_egg.png b/public/images/items/legendary_egg.png new file mode 100644 index 00000000000..291917d444c Binary files /dev/null and b/public/images/items/legendary_egg.png differ diff --git a/public/images/items/magnet.png b/public/images/items/magnet.png index f8668e72abd..13a602d7140 100644 Binary files a/public/images/items/magnet.png and b/public/images/items/magnet.png differ diff --git a/public/images/items/manaphy_egg.png b/public/images/items/manaphy_egg.png new file mode 100644 index 00000000000..2b5d8aa702a Binary files /dev/null and b/public/images/items/manaphy_egg.png differ diff --git a/public/images/items/master_ribbon.png b/public/images/items/master_ribbon.png index a8a181a52a0..710571d96ad 100644 Binary files a/public/images/items/master_ribbon.png and b/public/images/items/master_ribbon.png differ diff --git a/public/images/items/max_mushrooms.png b/public/images/items/max_mushrooms.png index 10ff9f5a72f..e1b066b0267 100644 Binary files a/public/images/items/max_mushrooms.png and b/public/images/items/max_mushrooms.png differ diff --git a/public/images/items/mega_bracelet.png b/public/images/items/mega_bracelet.png index 674c59a8f5a..5dde0be94ac 100644 Binary files a/public/images/items/mega_bracelet.png and b/public/images/items/mega_bracelet.png differ diff --git a/public/images/items/mint_atk.png b/public/images/items/mint_atk.png index f42e0cccfc0..0af6364f09c 100644 Binary files a/public/images/items/mint_atk.png and b/public/images/items/mint_atk.png differ diff --git a/public/images/items/n_solarizer.png b/public/images/items/n_solarizer.png index 787d2b49bc4..6060fe4e5fb 100644 Binary files a/public/images/items/n_solarizer.png and b/public/images/items/n_solarizer.png differ diff --git a/public/images/items/poison_barb.png b/public/images/items/poison_barb.png index b85f7d3b777..0454c5b5e78 100644 Binary files a/public/images/items/poison_barb.png and b/public/images/items/poison_barb.png differ diff --git a/public/images/items/power_herb.png b/public/images/items/power_herb.png index 477e32e3271..9f877f62396 100644 Binary files a/public/images/items/power_herb.png and b/public/images/items/power_herb.png differ diff --git a/public/images/items/rare_egg.png b/public/images/items/rare_egg.png new file mode 100644 index 00000000000..b3da4eaaf44 Binary files /dev/null and b/public/images/items/rare_egg.png differ diff --git a/public/images/items/rayquazite.png b/public/images/items/rayquazite.png index 6617924c434..80f467522fd 100644 Binary files a/public/images/items/rayquazite.png and b/public/images/items/rayquazite.png differ diff --git a/public/images/items/ribbon_gen4.png b/public/images/items/ribbon_gen4.png index ad4cb139a7e..a7765d1de50 100644 Binary files a/public/images/items/ribbon_gen4.png and b/public/images/items/ribbon_gen4.png differ diff --git a/public/images/items/ribbon_gen5.png b/public/images/items/ribbon_gen5.png index a4f99ffb7f2..00b84aab978 100644 Binary files a/public/images/items/ribbon_gen5.png and b/public/images/items/ribbon_gen5.png differ diff --git a/public/images/items/rogue_egg.png b/public/images/items/rogue_egg.png new file mode 100644 index 00000000000..a143b5f863c Binary files /dev/null and b/public/images/items/rogue_egg.png differ diff --git a/public/images/items/rogue_ribbon.png b/public/images/items/rogue_ribbon.png index 6864b6a1fb7..0482d193527 100644 Binary files a/public/images/items/rogue_ribbon.png and b/public/images/items/rogue_ribbon.png differ diff --git a/public/images/items/sceptilite.png b/public/images/items/sceptilite.png index 4b255b1ff6d..4411c172826 100644 Binary files a/public/images/items/sceptilite.png and b/public/images/items/sceptilite.png differ diff --git a/public/images/items/scroll_of_waters.png b/public/images/items/scroll_of_waters.png index 9195a26abe1..adacf66398f 100644 Binary files a/public/images/items/scroll_of_waters.png and b/public/images/items/scroll_of_waters.png differ diff --git a/public/images/items/soothe_bell.png b/public/images/items/soothe_bell.png index d21da03f663..8ca868108d3 100644 Binary files a/public/images/items/soothe_bell.png and b/public/images/items/soothe_bell.png differ diff --git a/public/images/items/sweet_apple.png b/public/images/items/sweet_apple.png index de183d1c644..591961604f8 100644 Binary files a/public/images/items/sweet_apple.png and b/public/images/items/sweet_apple.png differ diff --git a/public/images/items/tm_ice.png b/public/images/items/tm_ice.png index eece8623654..26354211f6d 100644 Binary files a/public/images/items/tm_ice.png and b/public/images/items/tm_ice.png differ diff --git a/public/images/items/tm_normal.png b/public/images/items/tm_normal.png index cede4cb96e2..8bc5e6b6a24 100644 Binary files a/public/images/items/tm_normal.png and b/public/images/items/tm_normal.png differ diff --git a/public/images/items/toxic_orb.png b/public/images/items/toxic_orb.png index 8b8a1026f92..f18a55c43dc 100644 Binary files a/public/images/items/toxic_orb.png and b/public/images/items/toxic_orb.png differ diff --git a/public/images/items/ultra_ribbon.png b/public/images/items/ultra_ribbon.png index f1342eb3bae..2fb3762a493 100644 Binary files a/public/images/items/ultra_ribbon.png and b/public/images/items/ultra_ribbon.png differ diff --git a/public/images/items/unknown.png b/public/images/items/unknown.png index 17697d0d640..7a1dc347093 100644 Binary files a/public/images/items/unknown.png and b/public/images/items/unknown.png differ diff --git a/public/images/items/white_herb.png b/public/images/items/white_herb.png index 0729602fd15..9e6aa77eeff 100644 Binary files a/public/images/items/white_herb.png and b/public/images/items/white_herb.png differ diff --git a/public/images/items/wl_antidote.png b/public/images/items/wl_antidote.png index 18a74292dcf..3a60ed639a7 100644 Binary files a/public/images/items/wl_antidote.png and b/public/images/items/wl_antidote.png differ diff --git a/public/images/items/wl_awakening.png b/public/images/items/wl_awakening.png index 4fa59e2d10d..27bbd49253a 100644 Binary files a/public/images/items/wl_awakening.png and b/public/images/items/wl_awakening.png differ diff --git a/public/images/items/wl_burn_heal.png b/public/images/items/wl_burn_heal.png index 98fa6c11766..3bbf5298a1d 100644 Binary files a/public/images/items/wl_burn_heal.png and b/public/images/items/wl_burn_heal.png differ diff --git a/public/images/items/wl_custom_thief.png b/public/images/items/wl_custom_thief.png index aa6f9e0acc7..8d54f18e739 100644 Binary files a/public/images/items/wl_custom_thief.png and b/public/images/items/wl_custom_thief.png differ diff --git a/public/images/items/wl_elixir.png b/public/images/items/wl_elixir.png index e9b7b48ab87..8146091e46b 100644 Binary files a/public/images/items/wl_elixir.png and b/public/images/items/wl_elixir.png differ diff --git a/public/images/items/wl_ether.png b/public/images/items/wl_ether.png index 457f2bf0649..03be51f7532 100644 Binary files a/public/images/items/wl_ether.png and b/public/images/items/wl_ether.png differ diff --git a/public/images/items/wl_full_heal.png b/public/images/items/wl_full_heal.png index 361d432781a..2f0d58e201d 100644 Binary files a/public/images/items/wl_full_heal.png and b/public/images/items/wl_full_heal.png differ diff --git a/public/images/items/wl_hyper_potion.png b/public/images/items/wl_hyper_potion.png index 016c257a1eb..7d6028eb784 100644 Binary files a/public/images/items/wl_hyper_potion.png and b/public/images/items/wl_hyper_potion.png differ diff --git a/public/images/items/wl_ice_heal.png b/public/images/items/wl_ice_heal.png index 619d30d9ca9..3d94ca63a3b 100644 Binary files a/public/images/items/wl_ice_heal.png and b/public/images/items/wl_ice_heal.png differ diff --git a/public/images/items/wl_max_elixir.png b/public/images/items/wl_max_elixir.png index 4df3eaff10a..40ed8baa441 100644 Binary files a/public/images/items/wl_max_elixir.png and b/public/images/items/wl_max_elixir.png differ diff --git a/public/images/items/wl_max_ether.png b/public/images/items/wl_max_ether.png index 0e174f9eba4..eeaad41fa05 100644 Binary files a/public/images/items/wl_max_ether.png and b/public/images/items/wl_max_ether.png differ diff --git a/public/images/items/wl_max_potion.png b/public/images/items/wl_max_potion.png index 2f334795489..4c37c175e38 100644 Binary files a/public/images/items/wl_max_potion.png and b/public/images/items/wl_max_potion.png differ diff --git a/public/images/items/wl_paralyze_heal.png b/public/images/items/wl_paralyze_heal.png index ba9c172fa17..35d29b54452 100644 Binary files a/public/images/items/wl_paralyze_heal.png and b/public/images/items/wl_paralyze_heal.png differ diff --git a/public/images/items/wl_potion.png b/public/images/items/wl_potion.png index a70bba17b2f..cce66644ed9 100644 Binary files a/public/images/items/wl_potion.png and b/public/images/items/wl_potion.png differ diff --git a/public/images/items/wl_super_potion.png b/public/images/items/wl_super_potion.png index 5bf5dd8fc89..62177ddbb26 100644 Binary files a/public/images/items/wl_super_potion.png and b/public/images/items/wl_super_potion.png differ diff --git a/public/images/logo_fake.png b/public/images/logo_fake.png index 9fdb8724025..42d1aeca7a5 100755 Binary files a/public/images/logo_fake.png and b/public/images/logo_fake.png differ diff --git a/public/images/pokeball/gb_opening.png b/public/images/pokeball/gb_opening.png index 075aafeb460..4122b2ffbc8 100644 Binary files a/public/images/pokeball/gb_opening.png and b/public/images/pokeball/gb_opening.png differ diff --git a/public/images/pokeball/pb_open.png b/public/images/pokeball/pb_open.png index 0fdfa7b98fa..bfb8e592742 100644 Binary files a/public/images/pokeball/pb_open.png and b/public/images/pokeball/pb_open.png differ diff --git a/public/images/pokeball/pb_opening.png b/public/images/pokeball/pb_opening.png index 1a7136f186d..415d0f92f1f 100644 Binary files a/public/images/pokeball/pb_opening.png and b/public/images/pokeball/pb_opening.png differ diff --git a/public/images/pokeball/rb_open.png b/public/images/pokeball/rb_open.png index 3fe5f6e81c7..db65009898c 100644 Binary files a/public/images/pokeball/rb_open.png and b/public/images/pokeball/rb_open.png differ diff --git a/public/images/pokeball/ub_open.png b/public/images/pokeball/ub_open.png index 29e5ddac92f..c15a51329b6 100644 Binary files a/public/images/pokeball/ub_open.png and b/public/images/pokeball/ub_open.png differ diff --git a/public/images/pokeball/ub_opening.png b/public/images/pokeball/ub_opening.png index 0696c666d95..09f73970f3c 100644 Binary files a/public/images/pokeball/ub_opening.png and b/public/images/pokeball/ub_opening.png differ diff --git a/public/images/pokemon/variant/585-autumn_1.json b/public/images/pokemon/variant/585-autumn_1.json deleted file mode 100644 index 6d76c48b366..00000000000 --- a/public/images/pokemon/variant/585-autumn_1.json +++ /dev/null @@ -1,3044 +0,0 @@ -{ - "textures": [ - { - "image": "585-autumn_1.png", - "format": "RGBA8888", - "size": { - "w": 195, - "h": 195 - }, - "scale": 1, - "frames": [ - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 50, - "w": 34, - "h": 50 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 50, - "w": 34, - "h": 50 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 34, - "y": 50, - "w": 32, - "h": 50 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 34, - "y": 50, - "w": 32, - "h": 50 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 136, - "y": 48, - "w": 32, - "h": 50 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 136, - "y": 48, - "w": 32, - "h": 50 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 100, - "y": 95, - "w": 32, - "h": 50 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 100, - "y": 95, - "w": 32, - "h": 50 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 66, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 66, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 159, - "y": 98, - "w": 31, - "h": 50 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 159, - "y": 98, - "w": 31, - "h": 50 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:5895c9b7b58344bc7455a02f687ef539:4df09e0e04d5b04fdeaf36f9db9673f9:c7e45605bee4014fbf86a5b3a10eafef$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/585-autumn_1.png b/public/images/pokemon/variant/585-autumn_1.png deleted file mode 100644 index f90e0b52879..00000000000 Binary files a/public/images/pokemon/variant/585-autumn_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/585-spring_1.json b/public/images/pokemon/variant/585-spring_1.json deleted file mode 100644 index 991403fbb72..00000000000 --- a/public/images/pokemon/variant/585-spring_1.json +++ /dev/null @@ -1,3044 +0,0 @@ -{ - "textures": [ - { - "image": "585-spring_1.png", - "format": "RGBA8888", - "size": { - "w": 195, - "h": 195 - }, - "scale": 1, - "frames": [ - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 50, - "w": 34, - "h": 50 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 50, - "w": 34, - "h": 50 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 34, - "y": 50, - "w": 32, - "h": 50 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 34, - "y": 50, - "w": 32, - "h": 50 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 136, - "y": 48, - "w": 32, - "h": 50 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 136, - "y": 48, - "w": 32, - "h": 50 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 100, - "y": 95, - "w": 32, - "h": 50 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 100, - "y": 95, - "w": 32, - "h": 50 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 66, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 66, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 159, - "y": 98, - "w": 31, - "h": 50 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 159, - "y": 98, - "w": 31, - "h": 50 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:23cc18b62ef0b3cf727c8495ccc3a48d:365d365196678a0a4e9440fb5e5291d6:d9f005b1786551ef1a4ec5614dcbbfd1$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/585-spring_1.png b/public/images/pokemon/variant/585-spring_1.png deleted file mode 100644 index 8d7cbe10c45..00000000000 Binary files a/public/images/pokemon/variant/585-spring_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/585-summer_1.json b/public/images/pokemon/variant/585-summer_1.json deleted file mode 100644 index 3205f992b9d..00000000000 --- a/public/images/pokemon/variant/585-summer_1.json +++ /dev/null @@ -1,3044 +0,0 @@ -{ - "textures": [ - { - "image": "585-summer_1.png", - "format": "RGBA8888", - "size": { - "w": 195, - "h": 195 - }, - "scale": 1, - "frames": [ - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 50, - "w": 34, - "h": 50 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 50, - "w": 34, - "h": 50 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 34, - "y": 50, - "w": 32, - "h": 50 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 34, - "y": 50, - "w": 32, - "h": 50 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 136, - "y": 48, - "w": 32, - "h": 50 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 136, - "y": 48, - "w": 32, - "h": 50 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 100, - "y": 95, - "w": 32, - "h": 50 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 100, - "y": 95, - "w": 32, - "h": 50 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 66, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 66, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 159, - "y": 98, - "w": 31, - "h": 50 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 159, - "y": 98, - "w": 31, - "h": 50 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:4f8e7854552697b480b552af7c1d0183:e954dc679a09ff9ec6b27dce5650d4be:6dee9c999116e929b40748d359d41e33$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/585-summer_1.png b/public/images/pokemon/variant/585-summer_1.png deleted file mode 100644 index 71646cca31c..00000000000 Binary files a/public/images/pokemon/variant/585-summer_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/585-winter_1.json b/public/images/pokemon/variant/585-winter_1.json deleted file mode 100644 index 54dc7476add..00000000000 --- a/public/images/pokemon/variant/585-winter_1.json +++ /dev/null @@ -1,3044 +0,0 @@ -{ - "textures": [ - { - "image": "585-winter_1.png", - "format": "RGBA8888", - "size": { - "w": 195, - "h": 195 - }, - "scale": 1, - "frames": [ - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 50 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 50, - "w": 34, - "h": 50 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 34, - "h": 50 - }, - "frame": { - "x": 0, - "y": 50, - "w": 34, - "h": 50 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 0, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 33, - "y": 100, - "w": 33, - "h": 50 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 33, - "h": 50 - }, - "frame": { - "x": 34, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 34, - "y": 50, - "w": 32, - "h": 50 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 34, - "y": 50, - "w": 32, - "h": 50 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 35, - "h": 49 - }, - "frame": { - "x": 67, - "y": 0, - "w": 35, - "h": 49 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 35, - "h": 48 - }, - "frame": { - "x": 102, - "y": 0, - "w": 35, - "h": 48 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 48 - }, - "frame": { - "x": 137, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 47 - }, - "frame": { - "x": 102, - "y": 48, - "w": 34, - "h": 47 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 1, - "y": 1, - "w": 33, - "h": 49 - }, - "frame": { - "x": 67, - "y": 49, - "w": 33, - "h": 49 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 136, - "y": 48, - "w": 32, - "h": 50 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 136, - "y": 48, - "w": 32, - "h": 50 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 100, - "y": 95, - "w": 32, - "h": 50 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 2, - "y": 0, - "w": 32, - "h": 50 - }, - "frame": { - "x": 100, - "y": 95, - "w": 32, - "h": 50 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 66, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 66, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 97, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 128, - "y": 145, - "w": 31, - "h": 50 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 159, - "y": 98, - "w": 31, - "h": 50 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 36, - "h": 50 - }, - "spriteSourceSize": { - "x": 3, - "y": 0, - "w": 31, - "h": 50 - }, - "frame": { - "x": 159, - "y": 98, - "w": 31, - "h": 50 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:9bd843fda4a1d50b9c8f6d76bca812d5:666a2e9254f313a4482e94557b5a4abd:9fc9970f730df71c344de29f38668796$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/585-winter_1.png b/public/images/pokemon/variant/585-winter_1.png deleted file mode 100644 index 4b4a179e8a4..00000000000 Binary files a/public/images/pokemon/variant/585-winter_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/586-autumn.json b/public/images/pokemon/variant/586-autumn.json deleted file mode 100644 index 9345bdee6c4..00000000000 --- a/public/images/pokemon/variant/586-autumn.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "0": { - "422110": "9d4f62", - "4a0808": "7f334a", - "dec56b": "ffd5f6", - "633121": "c66479", - "7b5231": "d98997", - "a57b4a": "e1b2d7", - "de8c29": "ffecfb" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/586-spring.json b/public/images/pokemon/variant/586-spring.json deleted file mode 100644 index 2518667eb20..00000000000 --- a/public/images/pokemon/variant/586-spring.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "0": { - "4a1008": "7f334a", - "dec56b": "ffd5f6", - "633a21": "c66479", - "422119": "9d4f62", - "de9429": "ffecfb", - "7b5a31": "d98997", - "a57b4a": "e1b2d7" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/586-summer.json b/public/images/pokemon/variant/586-summer.json deleted file mode 100644 index 0f89496c1fc..00000000000 --- a/public/images/pokemon/variant/586-summer.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "0": { - "193a29": "314a29", - "088c42": "4a8b4a", - "195a31": "416a39", - "dec56b": "ffd5f6", - "4a1008": "783046", - "422119": "944b5c", - "633a21": "bb5f73", - "7b5a31": "cc818e", - "a57b4a": "e1b2d7", - "de9429": "ffecfb", - "311010": "582333" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/586-winter.json b/public/images/pokemon/variant/586-winter.json deleted file mode 100644 index 352a4c57920..00000000000 --- a/public/images/pokemon/variant/586-winter.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "0": { - "6b6b6b": "cf9bc4", - "424a42": "b184a8", - "ffffff": "ffd5f6", - "adadad": "e1b2d7", - "4a1008": "7f334a", - "dec56b": "ffecfb", - "422119": "9d4f62", - "7b5a31": "d98997", - "633a21": "c66479", - "a57b4a": "e1b2d7", - "de9429": "ffecfb" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/_masterlist.json b/public/images/pokemon/variant/_masterlist.json index 8069cd354ef..8baf50791e2 100644 --- a/public/images/pokemon/variant/_masterlist.json +++ b/public/images/pokemon/variant/_masterlist.json @@ -515,14 +515,6 @@ "577": [1, 1, 1], "578": [1, 1, 1], "579": [1, 1, 1], - "585-autumn": [2, 0, 0], - "585-spring": [2, 0, 0], - "585-summer": [2, 0, 0], - "585-winter": [2, 0, 0], - "586-autumn": [1, 0, 0], - "586-spring": [1, 0, 0], - "586-summer": [1, 0, 0], - "586-winter": [1, 0, 0], "587": [0, 1, 1], "588": [0, 1, 1], "589": [0, 1, 1], @@ -1521,14 +1513,6 @@ "577": [1, 1, 1], "578": [1, 1, 1], "579": [1, 1, 1], - "585-autumn": [2, 0, 0], - "585-spring": [2, 0, 0], - "585-summer": [1, 0, 0], - "585-winter": [2, 0, 0], - "586-autumn": [1, 0, 0], - "586-spring": [1, 0, 0], - "586-summer": [1, 0, 0], - "586-winter": [1, 0, 0], "587": [0, 1, 1], "588": [0, 1, 1], "589": [0, 1, 1], diff --git a/public/images/pokemon/variant/back/585-autumn_1.json b/public/images/pokemon/variant/back/585-autumn_1.json deleted file mode 100644 index 383f34db8c2..00000000000 --- a/public/images/pokemon/variant/back/585-autumn_1.json +++ /dev/null @@ -1,3044 +0,0 @@ -{ - "textures": [ - { - "image": "585-autumn_1.png", - "format": "RGBA8888", - "size": { - "w": 185, - "h": 185 - }, - "scale": 1, - "frames": [ - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 155, - "y": 50, - "w": 30, - "h": 51 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 155, - "y": 50, - "w": 30, - "h": 51 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 30, - "y": 99, - "w": 30, - "h": 51 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 30, - "y": 99, - "w": 30, - "h": 51 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 100, - "w": 31, - "h": 51 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 100, - "w": 31, - "h": 51 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 91, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 91, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 122, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 122, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 153, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 153, - "y": 101, - "w": 31, - "h": 51 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:c49413af05ed6da998500793caadcb9e:881a2dc2dec7192eb5dd05f58b31eb4e:c7e45605bee4014fbf86a5b3a10eafef$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/585-autumn_1.png b/public/images/pokemon/variant/back/585-autumn_1.png deleted file mode 100644 index 49579e9b3f8..00000000000 Binary files a/public/images/pokemon/variant/back/585-autumn_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/back/585-spring_1.json b/public/images/pokemon/variant/back/585-spring_1.json deleted file mode 100644 index 219842b5f58..00000000000 --- a/public/images/pokemon/variant/back/585-spring_1.json +++ /dev/null @@ -1,3044 +0,0 @@ -{ - "textures": [ - { - "image": "585-spring_1.png", - "format": "RGBA8888", - "size": { - "w": 185, - "h": 185 - }, - "scale": 1, - "frames": [ - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 155, - "y": 50, - "w": 30, - "h": 51 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 155, - "y": 50, - "w": 30, - "h": 51 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 30, - "y": 99, - "w": 30, - "h": 51 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 30, - "y": 99, - "w": 30, - "h": 51 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 100, - "w": 31, - "h": 51 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 100, - "w": 31, - "h": 51 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 91, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 91, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 122, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 122, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 153, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 153, - "y": 101, - "w": 31, - "h": 51 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:2ab8bbf5cb2c6971847536eb2066eab3:d66b5d7c0285526a8d30873611f03457:d9f005b1786551ef1a4ec5614dcbbfd1$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/585-spring_1.png b/public/images/pokemon/variant/back/585-spring_1.png deleted file mode 100644 index 26c9d9cd408..00000000000 Binary files a/public/images/pokemon/variant/back/585-spring_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/back/585-summer.json b/public/images/pokemon/variant/back/585-summer.json deleted file mode 100644 index 6942da9df8d..00000000000 --- a/public/images/pokemon/variant/back/585-summer.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "0": { - "315231": "314a29", - "317b42": "416a39", - "42b542": "4a8b4a", - "ce9c08": "d89ca6", - "7b5210": "c16b7d", - "ffde52": "ffffff", - "bda58c": "d89ca6", - "9c7b5a": "c16b7d", - "f7efc5": "ffd5f6", - "524219": "783046", - "313131": "783046", - "525252": "c16b7d" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/585-winter_1.json b/public/images/pokemon/variant/back/585-winter_1.json deleted file mode 100644 index da0b49a548c..00000000000 --- a/public/images/pokemon/variant/back/585-winter_1.json +++ /dev/null @@ -1,3044 +0,0 @@ -{ - "textures": [ - { - "image": "585-winter_1.png", - "format": "RGBA8888", - "size": { - "w": 185, - "h": 185 - }, - "scale": 1, - "frames": [ - { - "filename": "0009.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0010.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0027.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0028.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0045.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0046.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0063.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0064.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0117.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0118.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0135.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0136.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 3, - "w": 34, - "h": 48 - }, - "frame": { - "x": 0, - "y": 0, - "w": 34, - "h": 48 - } - }, - { - "filename": "0007.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0008.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0025.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0026.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0043.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0044.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0061.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0062.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0115.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0116.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0133.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0134.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 34, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0011.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0012.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0029.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0030.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0047.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0048.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0065.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0066.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0119.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0120.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0137.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0138.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 2, - "w": 34, - "h": 49 - }, - "frame": { - "x": 68, - "y": 0, - "w": 34, - "h": 49 - } - }, - { - "filename": "0005.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0006.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0023.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0024.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0041.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0042.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0059.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0060.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0113.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0114.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0131.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0132.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 102, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0013.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0014.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0031.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0032.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0049.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0050.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0067.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0068.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0121.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0122.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0139.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0140.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 33, - "h": 50 - }, - "frame": { - "x": 135, - "y": 0, - "w": 33, - "h": 50 - } - }, - { - "filename": "0083.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0084.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0091.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0092.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0099.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0100.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 0, - "y": 48, - "w": 30, - "h": 50 - } - }, - { - "filename": "0087.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0088.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0095.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0096.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 1, - "w": 30, - "h": 50 - }, - "frame": { - "x": 30, - "y": 49, - "w": 30, - "h": 50 - } - }, - { - "filename": "0001.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0002.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0017.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0018.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0019.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0020.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0035.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0036.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0037.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0038.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0053.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0054.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0055.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0056.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0071.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0072.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0073.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0074.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0107.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0108.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0109.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0110.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0125.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0126.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0127.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0128.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0143.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0144.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 49, - "w": 31, - "h": 51 - } - }, - { - "filename": "0003.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0004.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0021.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0022.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0039.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0040.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0057.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0058.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0111.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0112.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0129.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0130.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 91, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0015.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0016.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0033.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0034.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0051.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0052.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0069.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0070.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0123.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0124.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0141.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0142.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 32, - "h": 51 - }, - "frame": { - "x": 123, - "y": 50, - "w": 32, - "h": 51 - } - }, - { - "filename": "0079.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 155, - "y": 50, - "w": 30, - "h": 51 - } - }, - { - "filename": "0080.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 155, - "y": 50, - "w": 30, - "h": 51 - } - }, - { - "filename": "0081.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0082.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0085.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0086.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0089.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0090.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0093.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0094.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0097.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0098.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 0, - "y": 98, - "w": 30, - "h": 51 - } - }, - { - "filename": "0101.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 30, - "y": 99, - "w": 30, - "h": 51 - } - }, - { - "filename": "0102.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 30, - "h": 51 - }, - "frame": { - "x": 30, - "y": 99, - "w": 30, - "h": 51 - } - }, - { - "filename": "0075.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 100, - "w": 31, - "h": 51 - } - }, - { - "filename": "0076.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 60, - "y": 100, - "w": 31, - "h": 51 - } - }, - { - "filename": "0077.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 91, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0078.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 91, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0103.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 122, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0104.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 122, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0105.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 153, - "y": 101, - "w": 31, - "h": 51 - } - }, - { - "filename": "0106.png", - "rotated": false, - "trimmed": true, - "sourceSize": { - "w": 34, - "h": 51 - }, - "spriteSourceSize": { - "x": 0, - "y": 0, - "w": 31, - "h": 51 - }, - "frame": { - "x": 153, - "y": 101, - "w": 31, - "h": 51 - } - } - ] - } - ], - "meta": { - "app": "https://www.codeandweb.com/texturepacker", - "version": "3.0", - "smartupdate": "$TexturePacker:SmartUpdate:c66354b4a5aadc73a00b2d5946887ffb:19cc871a12b36d15034bf4ae898ec955:9fc9970f730df71c344de29f38668796$" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/585-winter_1.png b/public/images/pokemon/variant/back/585-winter_1.png deleted file mode 100644 index 89421e43303..00000000000 Binary files a/public/images/pokemon/variant/back/585-winter_1.png and /dev/null differ diff --git a/public/images/pokemon/variant/back/586-autumn.json b/public/images/pokemon/variant/back/586-autumn.json deleted file mode 100644 index fea1b869102..00000000000 --- a/public/images/pokemon/variant/back/586-autumn.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "0": { - "7b5231": "d98997", - "422110": "9d4f62", - "633121": "c66479", - "de8c29": "ffecfb", - "a57b4a": "e1b2d7", - "dec56b": "ffd5f6" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/586-spring.json b/public/images/pokemon/variant/back/586-spring.json deleted file mode 100644 index 0b060156d33..00000000000 --- a/public/images/pokemon/variant/back/586-spring.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "0": { - "311010": "2a1418", - "731931": "5e263e", - "4a1008": "7f334a", - "633a21": "c66479", - "ce4263": "c66479", - "dec56b": "ffd5f6", - "422119": "9d4f62", - "7b5a31": "d98997", - "de9429": "ffecfb", - "dedede": "c8c8c8", - "a57b4a": "e1b2d7" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/586-summer.json b/public/images/pokemon/variant/back/586-summer.json deleted file mode 100644 index daafade5616..00000000000 --- a/public/images/pokemon/variant/back/586-summer.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "0": { - "193a29": "314a29", - "195a31": "416a39", - "088c42": "4a8b4a", - "4a1008": "7f334a", - "7b5a31": "d98997", - "422119": "9d4f62", - "633a21": "c66479", - "de9429": "ffecfb", - "a57b4a": "e1b2d7", - "dec56b": "ffd5f6" - } -} \ No newline at end of file diff --git a/public/images/pokemon/variant/back/586-winter.json b/public/images/pokemon/variant/back/586-winter.json deleted file mode 100644 index 6a9c9ed7400..00000000000 --- a/public/images/pokemon/variant/back/586-winter.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "0": { - "424a42": "99648f", - "ffffff": "ffd5f6", - "6b6b6b": "b184a8", - "adadad": "e1b2d7", - "4a1008": "7f334a", - "dec56b": "ffecfb", - "633a21": "c66479", - "422119": "9d4f62", - "7b5a31": "d98997", - "de9429": "ffecfb", - "a57b4a": "e1b2d7" - } -} \ No newline at end of file diff --git a/public/images/statuses_tl.png b/public/images/statuses_tl.png index 9f24c6a0810..cdec7a29e8b 100644 Binary files a/public/images/statuses_tl.png and b/public/images/statuses_tl.png differ diff --git a/public/images/trainer/aether_grunt_m.png b/public/images/trainer/aether_grunt_m.png index c61970f4c98..08ab681d2fc 100644 Binary files a/public/images/trainer/aether_grunt_m.png and b/public/images/trainer/aether_grunt_m.png differ diff --git a/public/images/trainer/allister.png b/public/images/trainer/allister.png index c29781660d1..7007a7365a9 100644 Binary files a/public/images/trainer/allister.png and b/public/images/trainer/allister.png differ diff --git a/public/images/trainer/aqua_grunt_m.png b/public/images/trainer/aqua_grunt_m.png index bddb6e9fa3c..771c88c9170 100644 Binary files a/public/images/trainer/aqua_grunt_m.png and b/public/images/trainer/aqua_grunt_m.png differ diff --git a/public/images/trainer/archie.png b/public/images/trainer/archie.png index 7b047322bfb..e684d847882 100644 Binary files a/public/images/trainer/archie.png and b/public/images/trainer/archie.png differ diff --git a/public/images/trainer/expert_pokemon_breeder.png b/public/images/trainer/expert_pokemon_breeder.png index 0c53da6f2dc..83e9bb99816 100644 Binary files a/public/images/trainer/expert_pokemon_breeder.png and b/public/images/trainer/expert_pokemon_breeder.png differ diff --git a/public/images/trainer/katy.png b/public/images/trainer/katy.png index 534abca0397..009293a8fc6 100644 Binary files a/public/images/trainer/katy.png and b/public/images/trainer/katy.png differ diff --git a/public/images/trainer/rocket_boss_giovanni_1.png b/public/images/trainer/rocket_boss_giovanni_1.png index 8adab2d0575..d7c2e0fe590 100644 Binary files a/public/images/trainer/rocket_boss_giovanni_1.png and b/public/images/trainer/rocket_boss_giovanni_1.png differ diff --git a/public/images/ui/boolean_sel.png b/public/images/ui/boolean_sel.png index 7f1c86fbb4d..020708801e0 100644 Binary files a/public/images/ui/boolean_sel.png and b/public/images/ui/boolean_sel.png differ diff --git a/public/images/ui/champion_ribbon.png b/public/images/ui/champion_ribbon.png index d70aa92daaf..b188f4c92d2 100644 Binary files a/public/images/ui/champion_ribbon.png and b/public/images/ui/champion_ribbon.png differ diff --git a/public/images/ui/champion_ribbon_bronze.png b/public/images/ui/champion_ribbon_bronze.png index 8d92b6e0ab1..b69efbb8f88 100644 Binary files a/public/images/ui/champion_ribbon_bronze.png and b/public/images/ui/champion_ribbon_bronze.png differ diff --git a/public/images/ui/champion_ribbon_diamond.png b/public/images/ui/champion_ribbon_diamond.png index 9effbe3669c..fd0e1f77480 100644 Binary files a/public/images/ui/champion_ribbon_diamond.png and b/public/images/ui/champion_ribbon_diamond.png differ diff --git a/public/images/ui/champion_ribbon_emerald.png b/public/images/ui/champion_ribbon_emerald.png index 81b111a05a9..4b0523f7f64 100644 Binary files a/public/images/ui/champion_ribbon_emerald.png and b/public/images/ui/champion_ribbon_emerald.png differ diff --git a/public/images/ui/champion_ribbon_silver.png b/public/images/ui/champion_ribbon_silver.png index c4dcd8d7be0..92b6f4cf8c7 100644 Binary files a/public/images/ui/champion_ribbon_silver.png and b/public/images/ui/champion_ribbon_silver.png differ diff --git a/public/images/ui/common_egg.png b/public/images/ui/common_egg.png new file mode 100644 index 00000000000..c449611d532 Binary files /dev/null and b/public/images/ui/common_egg.png differ diff --git a/public/images/ui/cursor.png b/public/images/ui/cursor.png index 0e2f9d98a16..961746a63db 100644 Binary files a/public/images/ui/cursor.png and b/public/images/ui/cursor.png differ diff --git a/public/images/ui/dawn_icon_fg.png b/public/images/ui/dawn_icon_fg.png index c64f0578073..30d793b509d 100644 Binary files a/public/images/ui/dawn_icon_fg.png and b/public/images/ui/dawn_icon_fg.png differ diff --git a/public/images/ui/day_icon_fg.png b/public/images/ui/day_icon_fg.png index a480e4d274d..24d470a70bc 100644 Binary files a/public/images/ui/day_icon_fg.png and b/public/images/ui/day_icon_fg.png differ diff --git a/public/images/ui/friendship_overlay.png b/public/images/ui/friendship_overlay.png index b6957ded371..8a7c2e55c38 100644 Binary files a/public/images/ui/friendship_overlay.png and b/public/images/ui/friendship_overlay.png differ diff --git a/public/images/ui/hall_of_fame_blue.png b/public/images/ui/hall_of_fame_blue.png index 2b799070cb1..4ef4e0bdeae 100644 Binary files a/public/images/ui/hall_of_fame_blue.png and b/public/images/ui/hall_of_fame_blue.png differ diff --git a/public/images/ui/hall_of_fame_red.png b/public/images/ui/hall_of_fame_red.png index df999ae631f..a7685d6cb71 100644 Binary files a/public/images/ui/hall_of_fame_red.png and b/public/images/ui/hall_of_fame_red.png differ diff --git a/public/images/ui/icon_egg_move.png b/public/images/ui/icon_egg_move.png index 3b79a6682d0..1356f6077b6 100644 Binary files a/public/images/ui/icon_egg_move.png and b/public/images/ui/icon_egg_move.png differ diff --git a/public/images/ui/legacy/champion_ribbon.png b/public/images/ui/legacy/champion_ribbon.png index d70aa92daaf..b188f4c92d2 100644 Binary files a/public/images/ui/legacy/champion_ribbon.png and b/public/images/ui/legacy/champion_ribbon.png differ diff --git a/public/images/ui/legacy/champion_ribbon_bronze.png b/public/images/ui/legacy/champion_ribbon_bronze.png index 8d92b6e0ab1..b69efbb8f88 100644 Binary files a/public/images/ui/legacy/champion_ribbon_bronze.png and b/public/images/ui/legacy/champion_ribbon_bronze.png differ diff --git a/public/images/ui/legacy/champion_ribbon_diamond.png b/public/images/ui/legacy/champion_ribbon_diamond.png index 9effbe3669c..fd0e1f77480 100644 Binary files a/public/images/ui/legacy/champion_ribbon_diamond.png and b/public/images/ui/legacy/champion_ribbon_diamond.png differ diff --git a/public/images/ui/legacy/champion_ribbon_emerald.png b/public/images/ui/legacy/champion_ribbon_emerald.png index 81b111a05a9..4b0523f7f64 100644 Binary files a/public/images/ui/legacy/champion_ribbon_emerald.png and b/public/images/ui/legacy/champion_ribbon_emerald.png differ diff --git a/public/images/ui/legacy/champion_ribbon_silver.png b/public/images/ui/legacy/champion_ribbon_silver.png index c4dcd8d7be0..92b6f4cf8c7 100644 Binary files a/public/images/ui/legacy/champion_ribbon_silver.png and b/public/images/ui/legacy/champion_ribbon_silver.png differ diff --git a/public/images/ui/legacy/common_egg.png b/public/images/ui/legacy/common_egg.png new file mode 100644 index 00000000000..c449611d532 Binary files /dev/null and b/public/images/ui/legacy/common_egg.png differ diff --git a/public/images/ui/legacy/cursor.png b/public/images/ui/legacy/cursor.png index deadae321e3..a2c271eebb2 100644 Binary files a/public/images/ui/legacy/cursor.png and b/public/images/ui/legacy/cursor.png differ diff --git a/public/images/ui/legacy/day_icon_fg.png b/public/images/ui/legacy/day_icon_fg.png index 79872f95202..a010c3ec9c4 100644 Binary files a/public/images/ui/legacy/day_icon_fg.png and b/public/images/ui/legacy/day_icon_fg.png differ diff --git a/public/images/ui/legacy/discord.png b/public/images/ui/legacy/discord.png index 1bb254b1594..e9acf219d3c 100644 Binary files a/public/images/ui/legacy/discord.png and b/public/images/ui/legacy/discord.png differ diff --git a/public/images/ui/legacy/friendship_overlay.png b/public/images/ui/legacy/friendship_overlay.png index b6957ded371..8a7c2e55c38 100644 Binary files a/public/images/ui/legacy/friendship_overlay.png and b/public/images/ui/legacy/friendship_overlay.png differ diff --git a/public/images/ui/legacy/hall_of_fame_blue.png b/public/images/ui/legacy/hall_of_fame_blue.png index 2b799070cb1..4ef4e0bdeae 100644 Binary files a/public/images/ui/legacy/hall_of_fame_blue.png and b/public/images/ui/legacy/hall_of_fame_blue.png differ diff --git a/public/images/ui/legacy/hall_of_fame_red.png b/public/images/ui/legacy/hall_of_fame_red.png index df999ae631f..a7685d6cb71 100644 Binary files a/public/images/ui/legacy/hall_of_fame_red.png and b/public/images/ui/legacy/hall_of_fame_red.png differ diff --git a/public/images/ui/legacy/icon_egg_move.png b/public/images/ui/legacy/icon_egg_move.png index 3b79a6682d0..1356f6077b6 100644 Binary files a/public/images/ui/legacy/icon_egg_move.png and b/public/images/ui/legacy/icon_egg_move.png differ diff --git a/public/images/ui/legacy/link_icon.png b/public/images/ui/legacy/link_icon.png index 1e20ab56ec7..faf3d64e752 100644 Binary files a/public/images/ui/legacy/link_icon.png and b/public/images/ui/legacy/link_icon.png differ diff --git a/public/images/ui/legacy/mystery_egg.png b/public/images/ui/legacy/mystery_egg.png deleted file mode 100644 index 83ad626da7e..00000000000 Binary files a/public/images/ui/legacy/mystery_egg.png and /dev/null differ diff --git a/public/images/ui/legacy/namebox.png b/public/images/ui/legacy/namebox.png index 5eea1504d77..766a07bdc2a 100644 Binary files a/public/images/ui/legacy/namebox.png and b/public/images/ui/legacy/namebox.png differ diff --git a/public/images/ui/legacy/overlay_hp.png b/public/images/ui/legacy/overlay_hp.png index 75607c199f5..56f9b50b734 100644 Binary files a/public/images/ui/legacy/overlay_hp.png and b/public/images/ui/legacy/overlay_hp.png differ diff --git a/public/images/ui/legacy/overlay_lv_alt.png b/public/images/ui/legacy/overlay_lv_alt.png index f7a76955e7b..92ec684bf75 100644 Binary files a/public/images/ui/legacy/overlay_lv_alt.png and b/public/images/ui/legacy/overlay_lv_alt.png differ diff --git a/public/images/ui/legacy/party_bg.png b/public/images/ui/legacy/party_bg.png index cdade735b4a..707db79f1e2 100644 Binary files a/public/images/ui/legacy/party_bg.png and b/public/images/ui/legacy/party_bg.png differ diff --git a/public/images/ui/legacy/party_bg_double.png b/public/images/ui/legacy/party_bg_double.png index 8e00bd6c293..3694e3edf3c 100644 Binary files a/public/images/ui/legacy/party_bg_double.png and b/public/images/ui/legacy/party_bg_double.png differ diff --git a/public/images/ui/legacy/party_bg_double_manage.png b/public/images/ui/legacy/party_bg_double_manage.png index 2bf2d63c315..d3954fc14ff 100644 Binary files a/public/images/ui/legacy/party_bg_double_manage.png and b/public/images/ui/legacy/party_bg_double_manage.png differ diff --git a/public/images/ui/legacy/party_slot_hp_overlay.png b/public/images/ui/legacy/party_slot_hp_overlay.png index 859adab148c..4f79d34c702 100644 Binary files a/public/images/ui/legacy/party_slot_hp_overlay.png and b/public/images/ui/legacy/party_slot_hp_overlay.png differ diff --git a/public/images/ui/legacy/party_slot_main_short.json b/public/images/ui/legacy/party_slot_main_short.json new file mode 100644 index 00000000000..d738d524a5b --- /dev/null +++ b/public/images/ui/legacy/party_slot_main_short.json @@ -0,0 +1,146 @@ +{ + "textures": [ + { + "image": "party_slot_main_short.png", + "format": "RGBA8888", + "size": { + "w": 110, + "h": 294 + }, + "scale": 1, + "frames": [ + { + "filename": "party_slot_main_short", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 110, + "h": 41 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 110, + "h": 41 + }, + "frame": { + "x": 0, + "y": 0, + "w": 110, + "h": 41 + } + }, + { + "filename": "party_slot_main_short_sel", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 110, + "h": 41 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 110, + "h": 41 + }, + "frame": { + "x": 0, + "y": 41, + "w": 110, + "h": 41 + } + }, + { + "filename": "party_slot_main_short_fnt", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 110, + "h": 41 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 110, + "h": 41 + }, + "frame": { + "x": 0, + "y": 82, + "w": 110, + "h": 41 + } + }, + { + "filename": "party_slot_main_short_fnt_sel", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 110, + "h": 41 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 110, + "h": 41 + }, + "frame": { + "x": 0, + "y": 123, + "w": 110, + "h": 41 + } + }, + { + "filename": "party_slot_main_short_swap", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 110, + "h": 41 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 110, + "h": 41 + }, + "frame": { + "x": 0, + "y": 164, + "w": 110, + "h": 41 + } + }, + { + "filename": "party_slot_main_short_swap_sel", + "rotated": false, + "trimmed": false, + "sourceSize": { + "w": 110, + "h": 41 + }, + "spriteSourceSize": { + "x": 0, + "y": 0, + "w": 110, + "h": 41 + }, + "frame": { + "x": 0, + "y": 205, + "w": 110, + "h": 41 + } + } + ] + } + ], + "meta": { + "app": "https://www.codeandweb.com/texturepacker", + "version": "3.0", + "smartupdate": "$TexturePacker:SmartUpdate:29685f2f538901cf5bf7f0ed2ea867c3:a080ea6c8cccd1e03244214053e79796:565f7afc5ca419b6ba8dbce51ea30818$" + } +} diff --git a/public/images/ui/legacy/party_slot_main_short.png b/public/images/ui/legacy/party_slot_main_short.png new file mode 100644 index 00000000000..54af35bd69c Binary files /dev/null and b/public/images/ui/legacy/party_slot_main_short.png differ diff --git a/public/images/ui/legacy/party_slot_overlay_lv_alt.png b/public/images/ui/legacy/party_slot_overlay_lv_alt.png index 387dfec6b22..7aa9a590a13 100644 Binary files a/public/images/ui/legacy/party_slot_overlay_lv_alt.png and b/public/images/ui/legacy/party_slot_overlay_lv_alt.png differ diff --git a/public/images/ui/legacy/passive_bg.png b/public/images/ui/legacy/passive_bg.png index 4a3fa1ec72b..8f89bfc29a2 100644 Binary files a/public/images/ui/legacy/passive_bg.png and b/public/images/ui/legacy/passive_bg.png differ diff --git a/public/images/ui/legacy/pb_tray_overlay_enemy.png b/public/images/ui/legacy/pb_tray_overlay_enemy.png index 86ac85f946f..70940db1c58 100644 Binary files a/public/images/ui/legacy/pb_tray_overlay_enemy.png and b/public/images/ui/legacy/pb_tray_overlay_enemy.png differ diff --git a/public/images/ui/legacy/pbinfo_enemy_type.png b/public/images/ui/legacy/pbinfo_enemy_type.png index 27cb481e861..8d3b956bb98 100644 Binary files a/public/images/ui/legacy/pbinfo_enemy_type.png and b/public/images/ui/legacy/pbinfo_enemy_type.png differ diff --git a/public/images/ui/legacy/pbinfo_enemy_type1.png b/public/images/ui/legacy/pbinfo_enemy_type1.png index df44b5bad5d..9e547234391 100644 Binary files a/public/images/ui/legacy/pbinfo_enemy_type1.png and b/public/images/ui/legacy/pbinfo_enemy_type1.png differ diff --git a/public/images/ui/legacy/pbinfo_enemy_type2.png b/public/images/ui/legacy/pbinfo_enemy_type2.png index df44b5bad5d..9e547234391 100644 Binary files a/public/images/ui/legacy/pbinfo_enemy_type2.png and b/public/images/ui/legacy/pbinfo_enemy_type2.png differ diff --git a/public/images/ui/legacy/pbinfo_player_type1.png b/public/images/ui/legacy/pbinfo_player_type1.png index df44b5bad5d..9e547234391 100644 Binary files a/public/images/ui/legacy/pbinfo_player_type1.png and b/public/images/ui/legacy/pbinfo_player_type1.png differ diff --git a/public/images/ui/legacy/pbinfo_player_type2.png b/public/images/ui/legacy/pbinfo_player_type2.png index df44b5bad5d..9e547234391 100644 Binary files a/public/images/ui/legacy/pbinfo_player_type2.png and b/public/images/ui/legacy/pbinfo_player_type2.png differ diff --git a/public/images/ui/legacy/pokedex_summary_bg.png b/public/images/ui/legacy/pokedex_summary_bg.png index 7323f99a913..0f8fed843c9 100644 Binary files a/public/images/ui/legacy/pokedex_summary_bg.png and b/public/images/ui/legacy/pokedex_summary_bg.png differ diff --git a/public/images/ui/legacy/prompt.png b/public/images/ui/legacy/prompt.png index d70362d1958..7781688f0ee 100644 Binary files a/public/images/ui/legacy/prompt.png and b/public/images/ui/legacy/prompt.png differ diff --git a/public/images/ui/legacy/saving_icon.png b/public/images/ui/legacy/saving_icon.png index 772fa91fb8c..02509d0e40c 100644 Binary files a/public/images/ui/legacy/saving_icon.png and b/public/images/ui/legacy/saving_icon.png differ diff --git a/public/images/ui/legacy/shiny.png b/public/images/ui/legacy/shiny.png index 362f8f48ff1..bc2a6c0d916 100644 Binary files a/public/images/ui/legacy/shiny.png and b/public/images/ui/legacy/shiny.png differ diff --git a/public/images/ui/legacy/summary_bg.png b/public/images/ui/legacy/summary_bg.png index 261b4974fb7..668a7438bf0 100644 Binary files a/public/images/ui/legacy/summary_bg.png and b/public/images/ui/legacy/summary_bg.png differ diff --git a/public/images/ui/legacy/summary_moves_cursor.png b/public/images/ui/legacy/summary_moves_cursor.png index 7375cedcdf6..6a17bccdffd 100644 Binary files a/public/images/ui/legacy/summary_moves_cursor.png and b/public/images/ui/legacy/summary_moves_cursor.png differ diff --git a/public/images/ui/legacy/summary_profile.png b/public/images/ui/legacy/summary_profile.png index 0b5b2ffec05..d8cfebb000e 100644 Binary files a/public/images/ui/legacy/summary_profile.png and b/public/images/ui/legacy/summary_profile.png differ diff --git a/public/images/ui/legacy/summary_profile_ability.png b/public/images/ui/legacy/summary_profile_ability.png index a803323564b..f839a6249f8 100644 Binary files a/public/images/ui/legacy/summary_profile_ability.png and b/public/images/ui/legacy/summary_profile_ability.png differ diff --git a/public/images/ui/legacy/summary_stats.png b/public/images/ui/legacy/summary_stats.png index 660fbee6df6..1da361f6157 100644 Binary files a/public/images/ui/legacy/summary_stats.png and b/public/images/ui/legacy/summary_stats.png differ diff --git a/public/images/ui/link_icon.png b/public/images/ui/link_icon.png index 1e20ab56ec7..faf3d64e752 100644 Binary files a/public/images/ui/link_icon.png and b/public/images/ui/link_icon.png differ diff --git a/public/images/ui/mystery_egg.png b/public/images/ui/mystery_egg.png deleted file mode 100644 index 83ad626da7e..00000000000 Binary files a/public/images/ui/mystery_egg.png and /dev/null differ diff --git a/public/images/ui/night_icon_fg.png b/public/images/ui/night_icon_fg.png index ef184e24435..9c173eeaa83 100644 Binary files a/public/images/ui/night_icon_fg.png and b/public/images/ui/night_icon_fg.png differ diff --git a/public/images/ui/night_icon_mg.png b/public/images/ui/night_icon_mg.png index f808e50b2c7..94b3529030c 100644 Binary files a/public/images/ui/night_icon_mg.png and b/public/images/ui/night_icon_mg.png differ diff --git a/public/images/ui/overlay_hp.png b/public/images/ui/overlay_hp.png index 9612ed8c4c2..8654174a2f1 100644 Binary files a/public/images/ui/overlay_hp.png and b/public/images/ui/overlay_hp.png differ diff --git a/public/images/ui/overlay_hp_boss.png b/public/images/ui/overlay_hp_boss.png index 5a011709e0c..215c3ff1158 100644 Binary files a/public/images/ui/overlay_hp_boss.png and b/public/images/ui/overlay_hp_boss.png differ diff --git a/public/images/ui/overlay_lv.png b/public/images/ui/overlay_lv.png index ee3f439f7be..6ced2da2660 100644 Binary files a/public/images/ui/overlay_lv.png and b/public/images/ui/overlay_lv.png differ diff --git a/public/images/ui/party_bg_double.png b/public/images/ui/party_bg_double.png index c4d381d828c..61cacc222d4 100644 Binary files a/public/images/ui/party_bg_double.png and b/public/images/ui/party_bg_double.png differ diff --git a/public/images/ui/party_slot_hp_bar.png b/public/images/ui/party_slot_hp_bar.png index 5381fe0a0b6..181bd04c0ea 100644 Binary files a/public/images/ui/party_slot_hp_bar.png and b/public/images/ui/party_slot_hp_bar.png differ diff --git a/public/images/ui/party_slot_overlay_lv.png b/public/images/ui/party_slot_overlay_lv.png index 3d7dafd6737..122d3f7151c 100644 Binary files a/public/images/ui/party_slot_overlay_lv.png and b/public/images/ui/party_slot_overlay_lv.png differ diff --git a/public/images/ui/passive_bg.png b/public/images/ui/passive_bg.png index 4a3fa1ec72b..8f89bfc29a2 100644 Binary files a/public/images/ui/passive_bg.png and b/public/images/ui/passive_bg.png differ diff --git a/public/images/ui/pbinfo_enemy_type1.png b/public/images/ui/pbinfo_enemy_type1.png index be28e1d2c65..bb0c37430ad 100644 Binary files a/public/images/ui/pbinfo_enemy_type1.png and b/public/images/ui/pbinfo_enemy_type1.png differ diff --git a/public/images/ui/pbinfo_player_type2.png b/public/images/ui/pbinfo_player_type2.png index be28e1d2c65..bb0c37430ad 100644 Binary files a/public/images/ui/pbinfo_player_type2.png and b/public/images/ui/pbinfo_player_type2.png differ diff --git a/public/images/ui/prompt.png b/public/images/ui/prompt.png index c045c5e91fe..06e1bce26e6 100644 Binary files a/public/images/ui/prompt.png and b/public/images/ui/prompt.png differ diff --git a/public/images/ui/saving_icon.png b/public/images/ui/saving_icon.png index 772fa91fb8c..02509d0e40c 100644 Binary files a/public/images/ui/saving_icon.png and b/public/images/ui/saving_icon.png differ diff --git a/public/images/ui/select_gen_cursor.png b/public/images/ui/select_gen_cursor.png index 7f1c86fbb4d..020708801e0 100644 Binary files a/public/images/ui/select_gen_cursor.png and b/public/images/ui/select_gen_cursor.png differ diff --git a/public/images/ui/select_gen_cursor_highlight.png b/public/images/ui/select_gen_cursor_highlight.png index cecc543ae56..76607a6cd62 100644 Binary files a/public/images/ui/select_gen_cursor_highlight.png and b/public/images/ui/select_gen_cursor_highlight.png differ diff --git a/public/images/ui/shiny.png b/public/images/ui/shiny.png index 362f8f48ff1..bc2a6c0d916 100644 Binary files a/public/images/ui/shiny.png and b/public/images/ui/shiny.png differ diff --git a/public/images/ui/summary_profile_ability.png b/public/images/ui/summary_profile_ability.png index a803323564b..f839a6249f8 100644 Binary files a/public/images/ui/summary_profile_ability.png and b/public/images/ui/summary_profile_ability.png differ diff --git a/public/locales b/public/locales index 1ea8f865e30..58fa5f9b6e9 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit 1ea8f865e30d1940caa0fceeabf37ae2e4689471 +Subproject commit 58fa5f9b6e94469017bfbe69bef992ed48ef5343 diff --git a/scripts/helpers/strings.js b/scripts/helpers/strings.js new file mode 100644 index 00000000000..3692bcfdd01 --- /dev/null +++ b/scripts/helpers/strings.js @@ -0,0 +1,179 @@ +// #region Split string code +// Regexps involved with splitting words in various case formats. +// Sourced from https://www.npmjs.com/package/change-case (with slight tweaking here and there) + +/** + * Regex to split at word boundaries. + * @type {RegExp} + */ +const SPLIT_LOWER_UPPER_RE = /([\p{Ll}\d])(\p{Lu})/gu; +/** + * Regex to split around single-letter uppercase words. + * @type {RegExp} + */ +const SPLIT_UPPER_UPPER_RE = /(\p{Lu})([\p{Lu}][\p{Ll}])/gu; +/** + * Regexp involved with stripping non-word delimiters from the result. + * @type {RegExp} + */ +const DELIM_STRIP_REGEXP = /[-_ ]+/giu; +// The replacement value for splits. +const SPLIT_REPLACE_VALUE = "$1\0$2"; + +/** + * Split any cased string into an array of its constituent words. + * @param {string} value + * @returns {string[]} The new string, delimited at each instance of one or more spaces, underscores, hyphens + * or lower-to-upper boundaries. + */ +function splitWords(value) { + let result = value.trim(); + result = result.replace(SPLIT_LOWER_UPPER_RE, SPLIT_REPLACE_VALUE).replace(SPLIT_UPPER_UPPER_RE, SPLIT_REPLACE_VALUE); + result = result.replace(DELIM_STRIP_REGEXP, "\0"); + // Trim the delimiter from around the output string + return trimFromStartAndEnd(result, "\0").split(/\0/g); +} + +/** + * Helper function to remove one or more sequences of characters from either end of a string. + * @param {string} str - The string to replace + * @param {string} charToTrim - The string to remove + * @returns {string} The string having been trimmed + */ +function trimFromStartAndEnd(str, charToTrim) { + let start = 0; + let end = str.length; + const blockLength = charToTrim.length; + while (str.startsWith(charToTrim, start)) { + start += blockLength; + } + if (start - end === blockLength) { + // Occurs if the ENTIRE string is made up of charToTrim (at which point we return nothing) + return ""; + } + while (str.endsWith(charToTrim, end)) { + end -= blockLength; + } + return str.slice(start, end); +} +// #endregion Split String code + +/** + * Capitalize the first letter of a string. + * @example + * ```ts + * console.log(capitalizeFirstLetter("consectetur adipiscing elit")); // returns "Consectetur adipiscing elit" + * ``` + * @param {string} str - The string whose first letter is to be capitalized + * @return {string} The original string with its first letter capitalized. + */ +export function capitalizeFirstLetter(str) { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +/** + * Helper method to convert a string into `Title Case` (such as one used for console logs). + * @example + * ```ts + * console.log(toTitleCase("lorem ipsum dolor sit amet")); // returns "Lorem Ipsum Dolor Sit Amet" + * ``` + * @param {string} str - The string being converted + * @returns {string} The result of converting `str` into title case. + */ +export function toTitleCase(str) { + return splitWords(str) + .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(" "); +} + +/** + * Helper method to convert a string into `camelCase` (such as one used for i18n keys). + * @example + * ```ts + * console.log(toCamelCase("BIG_ANGRY_TRAINER")); // returns "bigAngryTrainer" + * ``` + * @param {string} str - The string being converted + * @returns {string} The result of converting `str` into camel case. + */ +export function toCamelCase(str) { + return splitWords(str) + .map((word, index) => + index === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(), + ) + .join(""); +} + +/** + * Helper method to convert a string into `PascalCase`. + * @example + * ```ts + * console.log(toPascalCase("hi how was your day")); // returns "HiHowWasYourDay" + * ``` + * @param {string} str - The string being converted + * @returns {string} The result of converting `str` into pascal case. + */ +export function toPascalCase(str) { + return splitWords(str) + .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(""); +} + +/** + * Helper method to convert a string into `kebab-case` (such as one used for filenames). + * @example + * ```ts + * console.log(toKebabCase("not_kebab-caSe String")); // returns "not-kebab-case-string" + * ``` + * @param {string} str - The string being converted + * @returns {string} The result of converting `str` into kebab case. + */ +export function toKebabCase(str) { + return splitWords(str) + .map(word => word.toLowerCase()) + .join("-"); +} + +/** + * Helper method to convert a string into `snake_case` (such as one used for filenames). + * @example + * ```ts + * console.log(toSnakeCase("not-in snake_CaSe")); // returns "not_in_snake_case" + * ``` + * @param {string} str - The string being converted + * @returns {string} The result of converting `str` into snake case. + */ +export function toSnakeCase(str) { + return splitWords(str) + .map(word => word.toLowerCase()) + .join("_"); +} + +/** + * Helper method to convert a string into `UPPER_SNAKE_CASE`. + * @example + * ```ts + * console.log(toUpperSnakeCase("apples bananas_oranGes-PearS")); // returns "APPLES_BANANAS_ORANGES_PEARS" + * ``` + * @param {string} str - The string being converted + * @returns {string} The result of converting `str` into upper snake case. + */ +export function toUpperSnakeCase(str) { + return splitWords(str) + .map(word => word.toUpperCase()) + .join("_"); +} + +/** + * Helper method to convert a string into `Pascal_Snake_Case`. + * @example + * ```ts + * console.log(toPascalSnakeCase("apples-bananas_oranGes Pears")); // returns "Apples_Bananas_Oranges_Pears" + * ``` + * @param {string} str - The string being converted + * @returns {string} The result of converting `str` into pascal snake case. + */ +export function toPascalSnakeCase(str) { + return splitWords(str) + .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join("_"); +} diff --git a/scripts/scrape-trainer-names/check-gender.js b/scripts/scrape-trainer-names/check-gender.js new file mode 100644 index 00000000000..0a8d2aecdaa --- /dev/null +++ b/scripts/scrape-trainer-names/check-gender.js @@ -0,0 +1,53 @@ +/** + * Check if the given trainer class is female. + * @param {Document} document - The HTML document to scrape + * @returns {[gender: boolean, counterpartURLs: string[]]} A 2-length tuple containing: + * 1. The trainer class' gender (female or not) + * 2. A list of all the current class' opposite-gender counterparts (if the trainer has any). + */ +export function checkGenderAndType(document) { + const infoBox = document.getElementsByClassName("infobox")[0]; + if (!infoBox) { + return [false, []]; + } + // Find the row of the table containing the specified gender + const children = [...infoBox.getElementsByTagName("tr")]; + const genderCell = children.find(node => [...node.childNodes].some(c => c.textContent?.includes("Gender"))); + const tableBox = genderCell?.querySelector("td"); + if (!tableBox) { + return [false, []]; + } + + const gender = getGender(tableBox); + + // CHeck the cell's inner HTML for any `href`s to gender counterparts and scrape them too + const hrefExtractRegex = /href="\/wiki\/(.*?)_\(Trainer_class\)"/g; + const counterpartCell = children.find(node => [...node.childNodes].some(c => c.textContent?.includes("Counterpart"))); + + const counterpartURLs = []; + for (const url of counterpartCell?.innerHTML?.matchAll(hrefExtractRegex) ?? []) { + counterpartURLs.push(url[1]); + } + + return [gender, counterpartURLs]; +} + +/** + * Retrieve the gender from the given node text. + * @param {HTMLTableCellElement} genderCell - The cell to check + * @returns {boolean} The gender type + * @todo Handle trainers whose gender type has changed across different gens (Artists, etc.) + */ +function getGender(genderCell) { + const gender = genderCell.textContent?.trim().toLowerCase() ?? ""; + + switch (gender) { + case "female only": + return true; + case "male only": + case "both": + case undefined: + default: + return false; + } +} diff --git a/scripts/scrape-trainer-names/fetch-names.js b/scripts/scrape-trainer-names/fetch-names.js new file mode 100644 index 00000000000..9e6bd0c4d2b --- /dev/null +++ b/scripts/scrape-trainer-names/fetch-names.js @@ -0,0 +1,76 @@ +/** + * @import { parsedNames } from "./types.js"; + */ + +/** + * An error code for a bad URL. + */ +export const INVALID_URL = /** @type {const} */ ("bad_url_code"); + +/** + * Fetch a given trainer's names from the given HTML document. + * @param {HTMLElement | null | undefined} trainerListHeader - The header containing the trainer lists + * @param {boolean} [knownFemale=false] - Whether the class is known to be female; default `false` + * @returns {parsedNames | INVALID_URL} + * An object containing the parsed names. \ + * Will instead return with {@linkcode INVALID_URL} if the data is invalid. + */ +export function fetchNames(trainerListHeader, knownFemale = false) { + const trainerNames = /** @type {Set} */ (new Set()); + const femaleTrainerNames = /** @type {Set} */ (new Set()); + if (!trainerListHeader?.parentElement?.childNodes) { + // Return early if no child nodes (ie tables) can be found + return INVALID_URL; + } + + const elements = [...trainerListHeader.parentElement.childNodes]; + + // Find all elements within the "Trainer Names" header and selectively filter to find the name tables. + const startChildIndex = elements.indexOf(trainerListHeader); + const endChildIndex = elements.findIndex(h => h.nodeName === "H2" && elements.indexOf(h) > startChildIndex); + + // Grab all the trainer name tables sorted by generation + const tables = elements.slice(startChildIndex, endChildIndex).filter( + /** @type {(t: ChildNode) => t is Element} */ + ( + t => + // Only grab expandable tables within the header block + t.nodeName === "TABLE" && t["className"] === "expandable" + ), + ); + + parseTable(tables, knownFemale, trainerNames, femaleTrainerNames); + return { + male: Array.from(trainerNames), + female: Array.from(femaleTrainerNames), + }; +} + +/** + * Parse the table in question. + * @param {Element[]} tables - The array of Elements forming the current table + * @param {boolean} isFemale - Whether the trainer is known to be female or not + * @param {Set} trainerNames A Set containing the male trainer names + * @param {Set} femaleTrainerNames - A Set containing the female trainer names + */ +function parseTable(tables, isFemale, trainerNames, femaleTrainerNames) { + for (const table of tables) { + // Grab all rows past the first header with exactly 9 children in them (Name, Battle, Winnings, 6 party slots) + const trainerRows = [...table.querySelectorAll("tr:not(:first-child)")].filter(r => r.children.length === 9); + for (const row of trainerRows) { + const content = row.firstElementChild?.innerHTML; + // Skip empty elements & ones without anchors + if (!content || content?.indexOf(" ([a-z]+(?: & [a-z]+)?)<\/a>/i.exec(content); + if (!nameMatch) { + continue; + } + (female ? femaleTrainerNames : trainerNames).add(nameMatch[1].replace("&", "&")); + } + } +} diff --git a/scripts/scrape-trainer-names/help-message.js b/scripts/scrape-trainer-names/help-message.js new file mode 100644 index 00000000000..fe922a5e988 --- /dev/null +++ b/scripts/scrape-trainer-names/help-message.js @@ -0,0 +1,16 @@ +import chalk from "chalk"; + +/** Show help/usage text for the `scrape-trainers` CLI. */ +export function showHelpText() { + console.log(` +Usage: ${chalk.cyan("pnpm scrape-trainers [options] ")} +Note that all option names are ${chalk.bold("case insensitive")}. + +${chalk.hex("#8a2be2")("Arguments:")} + ${chalk.hex("#7fff00")("names")} The name of one or more trainer classes to parse. + +${chalk.hex("#ffa500")("Options:")} + ${chalk.blue("-h, --help")} Show this help message. + ${chalk.blue("-o, --out, --outfile")} The path to a file to save the output. If not provided, will send directly to stdout. +`); +} diff --git a/scripts/scrape-trainer-names/main.js b/scripts/scrape-trainer-names/main.js new file mode 100644 index 00000000000..43989eebab9 --- /dev/null +++ b/scripts/scrape-trainer-names/main.js @@ -0,0 +1,295 @@ +import { existsSync, writeFileSync } from "node:fs"; +import { format, inspect } from "node:util"; +import chalk from "chalk"; +import inquirer from "inquirer"; +import { JSDOM } from "jsdom"; +import { toCamelCase, toPascalSnakeCase, toTitleCase } from "../helpers/strings.js"; +import { checkGenderAndType } from "./check-gender.js"; +import { fetchNames, INVALID_URL } from "./fetch-names.js"; +import { showHelpText } from "./help-message.js"; + +/** + * @packageDocumentation + * This script will scrape Bulbapedia for the English names of a given trainer class, + * outputting them as JSON. + * Usage: `pnpm scrape-trainers` + */ + +/** + * @import { parsedNames } from "./types.js" + */ + +const version = "1.0.0"; +const OUTFILE_ALIASES = /** @type {const} */ (["-o", "--outfile", "--outFile"]); + +/** + * A large object mapping each "base" trainer name to a list of replacements. + * Used to allow for trainer classes with different `TrainerType`s than in mainline. + * @type {Record} + */ +const trainerNamesMap = { + pokemonBreeder: ["breeder"], + worker: ["worker", "snowWorker"], + richBoy: ["richKid"], + gentleman: ["rich"], +}; + +async function main() { + console.log(chalk.hex("#FF7F50")(`🍳 Trainer Name Scraper v${version}`)); + + const args = process.argv.slice(2); + const out = getOutfile(args); + // Break out if no args remain + if (args.length === 0) { + console.error( + chalk.red.bold( + `✗ Error: No trainer classes provided!\nArgs: ${chalk.hex("#7310fdff")(process.argv.slice(2).join(", "))}`, + ), + ); + showHelpText(); + process.exitCode = 1; + return; + } + + const output = await scrapeTrainerNames(args); + await tryWriteFile(out, output); +} + +/** + * Get the outfile location from the args array. + * @param {string[]} args - The command line arguments + * @returns {string | undefined} The outfile location, or `undefined` if none is provided + * @remarks + * This will mutate the `args` array by removing the outfile from the list of arguments. + */ +function getOutfile(args) { + let /** @type {string} */ outFile; + // Extract the outfile as either the form "-o=y" or "-o y". + const hasEquals = /^.*=(.+)$/g.exec(args[0]); + if (hasEquals) { + outFile = hasEquals[1]; + args.splice(0, 1); + } else if (/** @type {readonly string[]} */ (OUTFILE_ALIASES).includes(args[0])) { + outFile = args[1]; + args.splice(0, 2); + } else { + console.log(chalk.hex("#ffa500")("No outfile detected, logging to stdout...")); + return; + } + + console.log(chalk.hex("#ffa500")(`Using outfile: ${chalk.blue(outFile)}`)); + return outFile; +} + +/** + * Scrape the requested trainer names and format the resultant output. + * @param {string[]} classes The names of the trainer classes to retrieve + * @returns {Promise} A Promise that resolves with the finished text. + */ +async function scrapeTrainerNames(classes) { + classes = [...new Set(classes)]; + + /** + * A Set containing all trainer URLs that have been seen. + * @type {Set} + */ + const seenClasses = new Set(); + + /** + * A large array of tuples matching each class to their corresponding list of trainer names. \ + * Trainer classes with only 1 gender will only contain the single array for that gender. + * @type {[keyName: string, names: string[] | parsedNames][]} + */ + const namesTuples = await Promise.all( + classes.map(async trainerClass => { + try { + const [trainerName, names] = await doFetch(trainerClass, seenClasses); + const namesObj = names.female.length === 0 ? names.male : names; + return /** @type {const} */ ([trainerName, namesObj]); + } catch (e) { + if (!(e instanceof Error)) { + throw new Error(chalk.red.bold("Unrecognized error detected:", inspect(e))); + } + // If the error contains an HTTP status, attempt to parse the code to give a more friendly + // response than JSDOM's "Resource was not loaded"gi + const errCode = /Status: (\d*)/g.exec(e.message)?.[1]; + if (!errCode) { + throw e; + } + /** @type {string} */ + let reason; + switch (+errCode) { + case 404: + reason = "Page not found"; + break; + case 403: + reason = "Access is forbidden"; + break; + default: + reason = `Server produced error code of ${+errCode}`; + } + throw new Error( + chalk.red.bold(`Failed to parse URL for ${chalk.hex("#7fff00")(`\"${trainerClass}\"`)}!\nReason: ${reason}`), + ); + } + }), + ); + + // Grab all keys inside the name replacement map and change them accordingly. + const mappedNames = namesTuples.filter(tuple => tuple[0] in trainerNamesMap); + for (const mappedName of mappedNames) { + const namesMapping = trainerNamesMap[mappedName[0]]; + namesTuples.splice( + namesTuples.indexOf(mappedName), + 1, + ...namesMapping.map( + name => /** @type {[keyName: string, names: parsedNames | string[]]} */ ([name, mappedName[1]]), + ), + ); + } + + namesTuples.sort((a, b) => a[0].localeCompare(b[0])); + + /** @type {Record} */ + const namesRecord = Object.fromEntries(namesTuples); + + // Convert all arrays into objects indexed by numbers + return JSON.stringify( + namesRecord, + (_, v) => { + if (Array.isArray(v)) { + return v.reduce((ret, curr, i) => { + ret[i + 1] = curr; // 1 indexed + return ret; + }, {}); + } + return v; + }, + 2, + ); +} + +/** + * Recursively scrape names from a given Trainer class and its gender counterparts. + * @param {string} trainerClass - The URL to parse + * @param {Set} seenClasses - A Set containing all seen class URLs, used for record keeping. + * @returns {Promise<[string, parsedNames]>} + * A Promise that resolves with: + * 1. The name to use for the key. + * 2. All fetched names for this trainer class and its gender variants. + */ +async function doFetch(trainerClass, seenClasses) { + let keyName = toCamelCase(trainerClass); + // Bulba URLs are in Pascal_Snake_Case (Pokemon_Breeder) + const classURL = toPascalSnakeCase(trainerClass); + seenClasses.add(classURL); + + // Bulbapedia has redirects mapping basically all variant spellings of each trainer name to the corresponding main page. + // We thus rely on it + const { document } = (await JSDOM.fromURL(`https://bulbapedia.bulbagarden.net/wiki/${classURL}`)).window; + const trainerListHeader = document.querySelector("#Trainer_list")?.parentElement; + const [female, counterpartURLs] = checkGenderAndType(document); + const names = fetchNames(trainerListHeader, female); + if (names === INVALID_URL) { + return Promise.reject( + new Error(chalk.red.bold(`URL \"${classURL}\" did not correspond to a valid trainer class!`)), + ); + } + + // Recurse into all unseen gender counterparts' URLs, using the first male name we find + const counterpartNames = await Promise.all( + counterpartURLs + .filter(url => !seenClasses.has(url)) + .map(counterpartURL => { + console.log(chalk.green(`Accessing gender counterpart URL: ${toTitleCase(counterpartURL)}`)); + return doFetch(counterpartURL, seenClasses); + }), + ); + let overrodeName = false; + for (const [cKeyName, cNameObj] of counterpartNames) { + if (!overrodeName && female) { + overrodeName = true; + console.log(chalk.green(`Using "${cKeyName}" as the name of the JSON key object...`)); + keyName = cKeyName; + } + names.male = [...new Set(names.male.concat(cNameObj.male))]; + names.female = [...new Set(names.female.concat(cNameObj.female))]; + } + return [normalizeDiacritics(keyName), names]; +} + +/** + * Convert all diacritical marks within a string into their normalized variants. + * @param {string} str - The string to parse + * @returns {string} The string with normalized diacritics + */ +function normalizeDiacritics(str) { + // Normalizing to NFKD splits all diacritics into the base letter + grapheme (à -> a + `), + // which are conveniently all in their own little Unicode block for easy removal + return str.normalize("NFKD").replace(/[\u0300-\u036f]/g, ""); +} + +/** + * Try to write the output to a file (or log it to stdout, as the case may be). + * @param {string | undefined} outFile - The outfile + * @param {string} output - The scraped output to produce + */ +async function tryWriteFile(outFile, output) { + if (!outFile) { + console.log(output); + return; + } + + if (existsSync(outFile) && !(await promptExisting(outFile))) { + process.exitCode = 1; + return; + } + + try { + writeFileSync(outFile, output); + console.log(chalk.green.bold(`✔ Output written to ${chalk.blue(outFile)} successfully!`)); + } catch (e) { + let /** @type {string} */ errStr; + if (!(e instanceof Error)) { + errStr = format("Unknown error occurred: ", e); + } else { + // @ts-expect-error - Node.JS file errors always have codes + switch (e.code) { + case "ENOENT": + errStr = `File not found: ${outFile}`; + break; + case "EACCES": + errStr = `Could not write ${outFile}: Permission denied`; + break; + case "EISDIR": + errStr = `Unable to write to ${outFile} as it is a directory`; + break; + default: + errStr = `Error writing file: ${e.message}`; + } + } + console.error(chalk.red.bold(errStr)); + process.exitCode = 1; + return; + } +} + +/** + * Confirm overwriting an already-existing file. + * @param {string} outFile - The outfile + * @returns {Promise} Whether "Yes" or "No" was selected. + */ +async function promptExisting(outFile) { + return ( + await inquirer.prompt([ + { + type: "confirm", + name: "continue", + message: `File ${chalk.blue(outFile)} already exists!` + "\nDo you want to replace it?", + default: false, + }, + ]) + ).continue; +} + +main(); diff --git a/scripts/scrape-trainer-names/types.js b/scripts/scrape-trainer-names/types.js new file mode 100644 index 00000000000..0ea07db5164 --- /dev/null +++ b/scripts/scrape-trainer-names/types.js @@ -0,0 +1,9 @@ +/** + * @typedef {Object} + * parsedNames + * A parsed object containing the desired names. + * @property {string[]} male + * @property {string[]} female + */ + +export {}; diff --git a/src/@types/arena-tags.ts b/src/@types/arena-tags.ts index afcc8a0f924..4ac7abf6f3d 100644 --- a/src/@types/arena-tags.ts +++ b/src/@types/arena-tags.ts @@ -1,8 +1,10 @@ import type { ArenaTagTypeMap } from "#data/arena-tag"; import type { ArenaTagType } from "#enums/arena-tag-type"; +// biome-ignore lint/correctness/noUnusedImports: TSDocs +import type { SessionSaveData } from "#system/game-data"; /** Subset of {@linkcode ArenaTagType}s that apply some negative effect to pokemon that switch in ({@link https://bulbapedia.bulbagarden.net/wiki/List_of_moves_that_cause_entry_hazards#List_of_traps | entry hazards} and Imprison. */ -export type ArenaTrapTagType = +export type EntryHazardTagType = | ArenaTagType.STICKY_WEB | ArenaTagType.SPIKES | ArenaTagType.TOXIC_SPIKES @@ -19,6 +21,9 @@ export type TurnProtectArenaTagType = | ArenaTagType.MAT_BLOCK | ArenaTagType.CRAFTY_SHIELD; +/** Subset of {@linkcode ArenaTagType}s that create Trick Room-like effects which are removed upon overlap. */ +export type RoomArenaTagType = ArenaTagType.TRICK_ROOM; + /** Subset of {@linkcode ArenaTagType}s that cannot persist across turns, and thus should not be serialized in {@linkcode SessionSaveData}. */ export type NonSerializableArenaTagType = ArenaTagType.NONE | TurnProtectArenaTagType | ArenaTagType.ION_DELUGE; diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 4d3f190c02a..be02962867c 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -3684,15 +3684,8 @@ export class BattleScene extends SceneBase { ) { return false; } - if (this.gameMode.modeId === GameModes.CHALLENGE) { - const disallowedChallenges = encounterCandidate.disallowedChallenges; - if ( - disallowedChallenges && - disallowedChallenges.length > 0 && - this.gameMode.challenges.some(challenge => disallowedChallenges.includes(challenge.id)) - ) { - return false; - } + if (encounterCandidate.disallowedChallenges?.some(challenge => this.gameMode.hasChallenge(challenge))) { + return false; } if (!encounterCandidate.meetsRequirements()) { return false; diff --git a/src/constants.ts b/src/constants.ts index 17cf08aa7e2..589a091153c 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -53,6 +53,12 @@ export const defaultStarterSpecies: SpeciesId[] = [ SpeciesId.QUAXLY, ]; +export const defaultStarterSpeciesAndEvolutions: SpeciesId[] = defaultStarterSpecies.flatMap(id => [ + id, + (id + 1) as SpeciesId, + (id + 2) as SpeciesId, +]); + export const saveKey = "x0i2O7WRiANTqPmZ"; // Temporary; secure encryption is not yet necessary /** diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 03670835dbd..afac857395c 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -6,7 +6,7 @@ import type { SpeciesFormChangeRevertWeatherFormTrigger } from "#data/form-chang import { applyAbAttrs } from "#abilities/apply-ab-attrs"; import { globalScene } from "#app/global-scene"; import { getPokemonNameWithAffix } from "#app/messages"; -import type { ArenaTrapTag, SuppressAbilitiesTag } from "#data/arena-tag"; +import type { EntryHazardTag, SuppressAbilitiesTag } from "#data/arena-tag"; import type { BattlerTag } from "#data/battler-tags"; import { GroundedTag } from "#data/battler-tags"; import { getBerryEffectFunc } from "#data/berry"; @@ -1113,7 +1113,7 @@ export class PostDefendApplyArenaTrapTagAbAttr extends PostDefendAbAttr { } override canApply({ pokemon, opponent: attacker, move }: PostMoveInteractionAbAttrParams): boolean { - const tag = globalScene.arena.getTag(this.arenaTagType) as ArenaTrapTag; + const tag = globalScene.arena.getTag(this.arenaTagType) as EntryHazardTag; return ( this.condition(pokemon, attacker, move) && (!globalScene.arena.getTag(this.arenaTagType) || tag.layers < tag.maxLayers) @@ -1184,7 +1184,7 @@ export class PostDefendTypeChangeAbAttr extends PostDefendAbAttr { return i18next.t("abilityTriggers:postDefendTypeChange", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), abilityName, - typeName: i18next.t(`pokemonInfo:Type.${PokemonType[this.type]}`), + typeName: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[this.type])}`), }); } } @@ -1235,7 +1235,7 @@ export class PostDefendContactApplyStatusEffectAbAttr extends PostDefendAbAttr { // TODO: Probably want to check against simulated here const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; - attacker.trySetStatus(effect, true, pokemon); + attacker.trySetStatus(effect, pokemon); } } @@ -1749,7 +1749,7 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr { getTriggerMessage({ pokemon }: AugmentMoveInteractionAbAttrParams, _abilityName: string): string { return i18next.t("abilityTriggers:pokemonTypeChange", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - moveType: i18next.t(`pokemonInfo:Type.${PokemonType[this.moveType]}`), + moveType: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[this.moveType])}`), }); } } @@ -1758,7 +1758,7 @@ export class PokemonTypeChangeAbAttr extends PreAttackAbAttr { * Parameters for abilities that modify the hit count and damage of a move */ export interface AddSecondStrikeAbAttrParams extends Omit { - /** Holder for the number of hits. May be modified by ability application */ + /** Holder for the number of hits. May be modified by ability application */ hitCount?: NumberHolder; /** Holder for the damage multiplier _of the current hit_ */ multiplier?: NumberHolder; @@ -2228,7 +2228,7 @@ export class PostAttackApplyStatusEffectAbAttr extends PostAttackAbAttr { apply({ pokemon, opponent }: PostMoveInteractionAbAttrParams): void { const effect = this.effects.length === 1 ? this.effects[0] : this.effects[pokemon.randBattleSeedInt(this.effects.length)]; - opponent.trySetStatus(effect, true, pokemon); + opponent.trySetStatus(effect, pokemon); } } @@ -2383,7 +2383,7 @@ export class SynchronizeStatusAbAttr extends PostSetStatusAbAttr { */ override apply({ simulated, effect, sourcePokemon, pokemon }: PostSetStatusAbAttrParams): void { if (!simulated && sourcePokemon) { - sourcePokemon.trySetStatus(effect, true, pokemon); + sourcePokemon.trySetStatus(effect, pokemon); } } } @@ -3659,7 +3659,8 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { protected immuneEffects: StatusEffect[]; /** - * @param immuneEffects - The status effects to which the Pokémon is immune. + * @param immuneEffects - An array of {@linkcode StatusEffect}s to prevent application. + * If none are provided, will block **all** status effects regardless of type. */ constructor(...immuneEffects: StatusEffect[]) { super(); @@ -3668,7 +3669,7 @@ export class PreSetStatusEffectImmunityAbAttr extends PreSetStatusAbAttr { } override canApply({ effect }: PreSetStatusAbAttrParams): boolean { - return (effect !== StatusEffect.FAINT && this.immuneEffects.length < 1) || this.immuneEffects.includes(effect); + return (this.immuneEffects.length === 0 && effect !== StatusEffect.FAINT) || this.immuneEffects.includes(effect); } /** @@ -3720,6 +3721,11 @@ export interface UserFieldStatusEffectImmunityAbAttrParams extends AbAttrBasePar */ export class UserFieldStatusEffectImmunityAbAttr extends AbAttr { protected immuneEffects: StatusEffect[]; + + /** + * @param immuneEffects - An array of {@linkcode StatusEffect}s to prevent application. + * If none are provided, will block **all** status effects regardless of type. + */ constructor(...immuneEffects: StatusEffect[]) { super(); @@ -3728,7 +3734,7 @@ export class UserFieldStatusEffectImmunityAbAttr extends AbAttr { override canApply({ effect, cancelled }: UserFieldStatusEffectImmunityAbAttrParams): boolean { return ( - (!cancelled.value && effect !== StatusEffect.FAINT && this.immuneEffects.length < 1) || + (!cancelled.value && this.immuneEffects.length === 0 && effect !== StatusEffect.FAINT) || this.immuneEffects.includes(effect) ); } @@ -3754,6 +3760,10 @@ export class ConditionalUserFieldStatusEffectImmunityAbAttr extends UserFieldSta */ private condition: (target: Pokemon, source: Pokemon | null) => boolean; + /** + * @param immuneEffects - An array of {@linkcode StatusEffect}s to prevent application. + * If none are provided, will block **all** status effects regardless of type. + */ constructor(condition: (target: Pokemon, source: Pokemon | null) => boolean, ...immuneEffects: StatusEffect[]) { super(...immuneEffects); @@ -5814,7 +5824,7 @@ export class NoFusionAbilityAbAttr extends AbAttr { export interface IgnoreTypeImmunityAbAttrParams extends AbAttrBaseParams { /** The type of the move being used */ readonly moveType: PokemonType; - /** The type being checked for */ + /** The type being checked for */ readonly defenderType: PokemonType; /** Holds whether the type immunity should be bypassed */ cancelled: BooleanHolder; @@ -6222,7 +6232,9 @@ export class TerrainEventTypeChangeAbAttr extends PostSummonAbAttr { if (currentTerrain === TerrainType.NONE) { return i18next.t("abilityTriggers:pokemonTypeChangeRevert", { pokemonNameWithAffix }); } - const moveType = i18next.t(`pokemonInfo:Type.${PokemonType[this.determineTypeChange(pokemon, currentTerrain)[0]]}`); + const moveType = i18next.t( + `pokemonInfo:type.${toCamelCase(PokemonType[this.determineTypeChange(pokemon, currentTerrain)[0]])}`, + ); return i18next.t("abilityTriggers:pokemonTypeChange", { pokemonNameWithAffix, moveType }); } } @@ -7479,8 +7491,7 @@ export function initAbilities() { .unsuppressable() .bypassFaint(), new Ability(AbilityId.CORROSION, 7) - .attr(IgnoreTypeStatusEffectImmunityAbAttr, [ StatusEffect.POISON, StatusEffect.TOXIC ], [ PokemonType.STEEL, PokemonType.POISON ]) - .edgeCase(), // Should poison itself with toxic orb. + .attr(IgnoreTypeStatusEffectImmunityAbAttr, [ StatusEffect.POISON, StatusEffect.TOXIC ], [ PokemonType.STEEL, PokemonType.POISON ]), new Ability(AbilityId.COMATOSE, 7) .attr(StatusEffectImmunityAbAttr, ...getNonVolatileStatusEffects()) .attr(BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) @@ -7822,22 +7833,26 @@ export function initAbilities() { new Ability(AbilityId.TOXIC_CHAIN, 9) .attr(PostAttackApplyStatusEffectAbAttr, false, 30, StatusEffect.TOXIC), new Ability(AbilityId.EMBODY_ASPECT_TEAL, 9) - .attr(PostTeraFormChangeStatChangeAbAttr, [ Stat.SPD ], 1) + .attr(PostTeraFormChangeStatChangeAbAttr, [ Stat.SPD ], 1) // Activates immediately upon Terastallizing, as well as upon switching in while Terastallized + .conditionalAttr(pokemon => pokemon.isTerastallized, PostSummonStatStageChangeAbAttr, [ Stat.SPD ], 1, true) .uncopiable() .unreplaceable() // TODO is this true? .attr(NoTransformAbilityAbAttr), new Ability(AbilityId.EMBODY_ASPECT_WELLSPRING, 9) .attr(PostTeraFormChangeStatChangeAbAttr, [ Stat.SPDEF ], 1) + .conditionalAttr(pokemon => pokemon.isTerastallized, PostSummonStatStageChangeAbAttr, [ Stat.SPDEF ], 1, true) .uncopiable() .unreplaceable() .attr(NoTransformAbilityAbAttr), new Ability(AbilityId.EMBODY_ASPECT_HEARTHFLAME, 9) .attr(PostTeraFormChangeStatChangeAbAttr, [ Stat.ATK ], 1) + .conditionalAttr(pokemon => pokemon.isTerastallized, PostSummonStatStageChangeAbAttr, [ Stat.ATK ], 1, true) .uncopiable() .unreplaceable() .attr(NoTransformAbilityAbAttr), new Ability(AbilityId.EMBODY_ASPECT_CORNERSTONE, 9) .attr(PostTeraFormChangeStatChangeAbAttr, [ Stat.DEF ], 1) + .conditionalAttr(pokemon => pokemon.isTerastallized, PostSummonStatStageChangeAbAttr, [ Stat.DEF ], 1, true) .uncopiable() .unreplaceable() .attr(NoTransformAbilityAbAttr), diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 15c2cde1d58..b03cc5b951a 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -24,11 +24,12 @@ import type { Pokemon } from "#field/pokemon"; import type { ArenaScreenTagType, ArenaTagTypeData, - ArenaTrapTagType, + EntryHazardTagType, + RoomArenaTagType, SerializableArenaTagType, } from "#types/arena-tags"; import type { Mutable } from "#types/type-helpers"; -import { BooleanHolder, NumberHolder, toDmgValue } from "#utils/common"; +import { BooleanHolder, type NumberHolder, toDmgValue } from "#utils/common"; import i18next from "i18next"; /** @@ -294,7 +295,8 @@ export abstract class WeakenMoveScreenTag extends SerializableArenaTag { if (bypassed.value) { return false; } - damageMultiplier.value = globalScene.currentBattle.double ? 2732 / 4096 : 0.5; + // Screens are less effective in Double Battles + damageMultiplier.value = globalScene.currentBattle.double ? 2 / 3 : 1 / 2; return true; } return false; @@ -725,42 +727,79 @@ export class IonDelugeTag extends ArenaTag { } /** - * Abstract class to implement arena traps. + * Abstract class to implement [entry hazards](https://bulbapedia.bulbagarden.net/wiki/List_of_moves_that_cause_entry_hazards). + * These persistent tags remain on-field across turns and apply effects to any {@linkcode Pokemon} switching in. \ + * Uniquely, adding a tag multiple times may stack multiple "layers" of the effect, increasing its severity. */ -export abstract class ArenaTrapTag extends SerializableArenaTag { - abstract readonly tagType: ArenaTrapTagType; - public layers: number; - public maxLayers: number; - +export abstract class EntryHazardTag extends SerializableArenaTag { + public declare abstract readonly tagType: EntryHazardTagType; /** - * Creates a new instance of the ArenaTrapTag class. - * - * @param tagType - The type of the arena tag. - * @param sourceMove - The move that created the tag. - * @param sourceId - The ID of the source of the tag. - * @param side - The side (player or enemy) the tag affects. - * @param maxLayers - The maximum amount of layers this tag can have. + * The current number of layers this tag has. + * Starts at 1 and increases each time the trap is laid. */ - constructor(sourceMove: MoveId, sourceId: number | undefined, side: ArenaTagSide, maxLayers: number) { - super(0, sourceMove, sourceId, side); - - this.layers = 1; - this.maxLayers = maxLayers; + public layers = 1; + /** The maximum number of layers this tag can have. */ + public abstract get maxLayers(): number; + /** Whether this tag should only affect grounded targets; default `true` */ + protected get groundedOnly(): boolean { + return true; } - onOverlap(arena: Arena, _source: Pokemon | null): void { - if (this.layers < this.maxLayers) { - this.layers++; + constructor(sourceMove: MoveId, sourceId: number | undefined, side: ArenaTagSide) { + super(0, sourceMove, sourceId, side); + } - this.onAdd(arena); + // TODO: Add a `canAdd` field to arena tags to remove need for callers to check layer counts + + /** + * Display text when this tag is added to the field. + * @param _arena - The {@linkcode Arena} at the time of adding this tag + * @param quiet - Whether to suppress messages during tag creation; default `false` + */ + override onAdd(_arena: Arena, quiet = false): void { + // Here, `quiet=true` means "just add the tag, no questions asked" + if (quiet) { + return; } + + const source = this.getSourcePokemon(); + if (!source) { + console.warn( + "Failed to get source Pokemon for AernaTrapTag on add message!" + + `\nTag type: ${this.tagType}` + + `\nPID: ${this.sourceId}`, + ); + return; + } + + globalScene.phaseManager.queueMessage(this.getAddMessage(source)); } /** - * 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 + * Return the text to be displayed upon adding a new layer to this trap. + * @param source - The {@linkcode Pokemon} having created this tag + * @returns The localized message to be displayed on screen. + */ + protected abstract getAddMessage(source: Pokemon): string; + + /** + * Add a new layer to this tag upon overlap, triggering the tag's normal {@linkcode onAdd} effects upon doing so. + * @param arena - The {@linkcode arena} at the time of adding the tag + */ + override onOverlap(arena: Arena): void { + if (this.layers >= this.maxLayers) { + return; + } + this.layers++; + + this.onAdd(arena); + } + + /** + * Activate the hazard effect onto a Pokemon when it enters the field. + * @param _arena - The {@linkcode Arena} at the time of tag activation + * @param simulated - Whether to suppress activation effects during execution + * @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 { @@ -768,12 +807,21 @@ export abstract class ArenaTrapTag extends SerializableArenaTag { return false; } + if (this.groundedOnly && !pokemon.isGrounded()) { + return false; + } + return this.activateTrap(pokemon, simulated); } - activateTrap(_pokemon: Pokemon, _simulated: boolean): boolean { - return false; - } + /** + * Activate this trap's effects when a Pokemon switches into it. + * @param _pokemon - The {@linkcode Pokemon} + * @param _simulated - Whether the activation is simulated + * @returns Whether the trap activation succeeded + * @todo Do we need the return value? nothing uses it + */ + protected abstract activateTrap(_pokemon: Pokemon, _simulated: boolean): boolean; getMatchupScoreMultiplier(pokemon: Pokemon): number { return pokemon.isGrounded() @@ -781,141 +829,186 @@ export abstract class ArenaTrapTag extends SerializableArenaTag { : Phaser.Math.Linear(0, 1 / Math.pow(2, this.layers), Math.min(pokemon.getHpRatio(), 0.5) * 2); } - public loadTag(source: BaseArenaTag & Pick): void { + public loadTag(source: BaseArenaTag & Pick): void { super.loadTag(source); this.layers = source.layers; - this.maxLayers = source.maxLayers; } } +/** + * Abstract class to implement damaging entry hazards. + * Currently used for {@linkcode SpikesTag} and {@linkcode StealthRockTag}. + */ +abstract class DamagingTrapTag extends EntryHazardTag { + override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { + // Check for magic guard immunity + const cancelled = new BooleanHolder(false); + applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled }); + if (cancelled.value) { + return false; + } + + if (simulated) { + return true; + } + + // Damage the target and trigger a message + const damageHpRatio = this.getDamageHpRatio(pokemon); + const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio); + + globalScene.phaseManager.queueMessage(this.getTriggerMessage(pokemon)); + pokemon.damageAndUpdate(damage, { result: HitResult.INDIRECT }); + pokemon.turnData.damageTaken += damage; + return true; + } + + /** + * Return the text to be displayed when this tag deals damage. + * @param _pokemon - The {@linkcode Pokemon} switching in + * @returns The localized trigger message to be displayed on-screen. + */ + protected abstract getTriggerMessage(_pokemon: Pokemon): string; + + /** + * Return the amount of damage this tag should deal to the given Pokemon, relative to its maximum HP. + * @param _pokemon - The {@linkcode Pokemon} switching in + * @returns The percentage of max HP to deal upon activation. + */ + protected abstract getDamageHpRatio(_pokemon: Pokemon): number; +} + /** * Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Spikes_(move) Spikes}. * Applies up to 3 layers of Spikes, dealing 1/8th, 1/6th, or 1/4th of the the Pokémon's HP * in damage for 1, 2, or 3 layers of Spikes respectively if they are summoned into this trap. */ -class SpikesTag extends ArenaTrapTag { +class SpikesTag extends DamagingTrapTag { public readonly tagType = ArenaTagType.SPIKES; + override get maxLayers() { + return 3 as const; + } + constructor(sourceId: number | undefined, side: ArenaTagSide) { - super(MoveId.SPIKES, sourceId, side, 3); + super(MoveId.SPIKES, sourceId, side); } - onAdd(arena: Arena, quiet = false): void { - super.onAdd(arena); - - // We assume `quiet=true` means "just add the bloody tag no questions asked" - if (quiet) { - return; - } - - const source = this.getSourcePokemon(); - if (!source) { - console.warn(`Failed to get source Pokemon for SpikesTag on add message; id: ${this.sourceId}`); - return; - } - - globalScene.phaseManager.queueMessage( - i18next.t("arenaTag:spikesOnAdd", { - moveName: this.getMoveName(), - opponentDesc: source.getOpponentDescriptor(), - }), - ); + protected override getAddMessage(source: Pokemon): string { + return i18next.t("arenaTag:spikesOnAdd", { + moveName: this.getMoveName(), + opponentDesc: source.getOpponentDescriptor(), + }); } - override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { - if (!pokemon.isGrounded()) { - return false; - } + protected override getTriggerMessage(pokemon: Pokemon): string { + return i18next.t("arenaTag:spikesActivateTrap", { + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + }); + } - const cancelled = new BooleanHolder(false); - applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled }); - if (simulated || cancelled.value) { - return !cancelled.value; - } - - const damageHpRatio = 1 / (10 - 2 * this.layers); - const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio); - - globalScene.phaseManager.queueMessage( - i18next.t("arenaTag:spikesActivateTrap", { - pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - }), - ); - pokemon.damageAndUpdate(damage, { result: HitResult.INDIRECT }); - pokemon.turnData.damageTaken += damage; - return true; + protected override getDamageHpRatio(_pokemon: Pokemon): number { + // 1/8 for 1 layer, 1/6 for 2, 1/4 for 3 + return 1 / (10 - 2 * this.layers); } } /** - * Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Spikes_(move) Toxic Spikes}. - * Applies up to 2 layers of Toxic Spikes, poisoning or badly poisoning any Pokémon who is - * summoned into this trap if 1 or 2 layers of Toxic Spikes respectively are up. Poison-type - * Pokémon summoned into this trap remove it entirely. + * Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Stealth_Rock_(move) | Stealth Rock}. + * Applies up to 1 layer of Stealth Rocks, dealing percentage-based damage to any Pokémon + * who is summoned into the trap based on the Rock type's type effectiveness. */ -class ToxicSpikesTag extends ArenaTrapTag { - #neutralized: boolean; - public readonly tagType = ArenaTagType.TOXIC_SPIKES; +class StealthRockTag extends DamagingTrapTag { + public readonly tagType = ArenaTagType.STEALTH_ROCK; + public override get maxLayers() { + return 1 as const; + } + protected override get groundedOnly() { + return false; + } constructor(sourceId: number | undefined, side: ArenaTagSide) { - super(MoveId.TOXIC_SPIKES, sourceId, side, 2); - this.#neutralized = false; + super(MoveId.STEALTH_ROCK, sourceId, side); } - onAdd(arena: Arena, quiet = false): void { - super.onAdd(arena); - - if (quiet) { - // We assume `quiet=true` means "just add the bloody tag no questions asked" - return; - } - - const source = this.getSourcePokemon(); - if (!source) { - console.warn(`Failed to get source Pokemon for ToxicSpikesTag on add message; id: ${this.sourceId}`); - return; - } - - globalScene.phaseManager.queueMessage( - i18next.t("arenaTag:toxicSpikesOnAdd", { - moveName: this.getMoveName(), - opponentDesc: source.getOpponentDescriptor(), - }), - ); + protected override getAddMessage(source: Pokemon): string { + return i18next.t("arenaTag:stealthRockOnAdd", { + opponentDesc: source.getOpponentDescriptor(), + }); } - onRemove(arena: Arena): void { + protected override getTriggerMessage(pokemon: Pokemon): string { + return i18next.t("arenaTag:stealthRockActivateTrap", { + pokemonName: getPokemonNameWithAffix(pokemon), + }); + } + + protected override getDamageHpRatio(pokemon: Pokemon): number { + const effectiveness = pokemon.getAttackTypeEffectiveness(PokemonType.ROCK, undefined, true); + return 0.125 * effectiveness; + } + + getMatchupScoreMultiplier(pokemon: Pokemon): number { + const damageHpRatio = this.getDamageHpRatio(pokemon); + return Phaser.Math.Linear(super.getMatchupScoreMultiplier(pokemon), 1, 1 - Math.pow(damageHpRatio, damageHpRatio)); + } +} + +/** + * Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Toxic_Spikes_(move) | Toxic Spikes}. + * Applies up to 2 layers of Toxic Spikes, poisoning or badly poisoning any Pokémon switched in + * based on the current layer count. \ + * Poison-type Pokémon will remove it entirely upon switch-in. + */ +class ToxicSpikesTag extends EntryHazardTag { + /** + * Whether the tag is currently in the process of being neutralized by a Poison-type. + * @defaultValue `false` + */ + #neutralized = false; + public readonly tagType = ArenaTagType.TOXIC_SPIKES; + override get maxLayers() { + return 2 as const; + } + + constructor(sourceId: number | undefined, side: ArenaTagSide) { + super(MoveId.TOXIC_SPIKES, sourceId, side); + } + + protected override getAddMessage(source: Pokemon): string { + return i18next.t("arenaTag:toxicSpikesOnAdd", { + moveName: this.getMoveName(), + opponentDesc: source.getOpponentDescriptor(), + }); + } + + // Override remove function to only display text when not neutralized + override onRemove(arena: Arena): void { if (!this.#neutralized) { super.onRemove(arena); } } override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { - if (pokemon.isGrounded()) { - if (simulated) { - return true; - } - if (pokemon.isOfType(PokemonType.POISON)) { - this.#neutralized = true; - if (globalScene.arena.removeTag(this.tagType)) { - globalScene.phaseManager.queueMessage( - i18next.t("arenaTag:toxicSpikesActivateTrapPoison", { - pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - moveName: this.getMoveName(), - }), - ); - return true; - } - } else if (!pokemon.status) { - const toxic = this.layers > 1; - if ( - pokemon.trySetStatus(!toxic ? StatusEffect.POISON : StatusEffect.TOXIC, true, null, 0, this.getMoveName()) - ) { - return true; - } - } + if (simulated) { + return true; } - return false; + if (pokemon.isOfType(PokemonType.POISON)) { + // Neutralize the tag and remove it from the field. + // Message cannot be moved to `onRemove` as that requires a reference to the neutralizing pokemon + this.#neutralized = true; + globalScene.arena.removeTagOnSide(this.tagType, this.side); + globalScene.phaseManager.queueMessage( + i18next.t("arenaTag:toxicSpikesActivateTrapPoison", { + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + moveName: this.getMoveName(), + }), + ); + return true; + } + + // Attempt to poison the target, suppressing any status effect messages + const effect = this.layers === 1 ? StatusEffect.POISON : StatusEffect.TOXIC; + return pokemon.trySetStatus(effect, null, 0, this.getMoveName(), false, true); } getMatchupScoreMultiplier(pokemon: Pokemon): number { @@ -930,71 +1023,37 @@ class ToxicSpikesTag extends ArenaTrapTag { } /** - * Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Stealth_Rock_(move) Stealth Rock}. - * Applies up to 1 layer of Stealth Rocks, dealing percentage-based damage to any Pokémon - * who is summoned into the trap, based on the Rock type's type effectiveness. + * Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Sticky_Web_(move) | Sticky Web}. + * Applies a single-layer trap that lowers the Speed of all grounded Pokémon switching in. */ -class StealthRockTag extends ArenaTrapTag { - public readonly tagType = ArenaTagType.STEALTH_ROCK; +class StickyWebTag extends EntryHazardTag { + public readonly tagType = ArenaTagType.STICKY_WEB; + public override get maxLayers() { + return 1 as const; + } + constructor(sourceId: number | undefined, side: ArenaTagSide) { - super(MoveId.STEALTH_ROCK, sourceId, side, 1); + super(MoveId.STICKY_WEB, sourceId, side); } - onAdd(arena: Arena, quiet = false): void { - super.onAdd(arena); - - if (quiet) { - return; - } - - const source = this.getSourcePokemon(); - if (!quiet && source) { - globalScene.phaseManager.queueMessage( - i18next.t("arenaTag:stealthRockOnAdd", { - opponentDesc: source.getOpponentDescriptor(), - }), - ); - } - } - - getDamageHpRatio(pokemon: Pokemon): number { - const effectiveness = pokemon.getAttackTypeEffectiveness(PokemonType.ROCK, undefined, true); - - let damageHpRatio = 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; - } - - return damageHpRatio; + protected override getAddMessage(source: Pokemon): string { + return i18next.t("arenaTag:stickyWebOnAdd", { + moveName: this.getMoveName(), + opponentDesc: source.getOpponentDescriptor(), + }); } override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { const cancelled = new BooleanHolder(false); - applyAbAttrs("BlockNonDirectDamageAbAttr", { pokemon, cancelled }); - if (cancelled.value) { - return false; - } + // TODO: Does this need to pass `simulated` as a parameter? + applyAbAttrs("ProtectStatAbAttr", { + pokemon, + cancelled, + stat: Stat.SPD, + stages: -1, + }); - const damageHpRatio = this.getDamageHpRatio(pokemon); - if (!damageHpRatio) { + if (cancelled.value) { return false; } @@ -1002,95 +1061,112 @@ class StealthRockTag extends ArenaTrapTag { return true; } - const damage = toDmgValue(pokemon.getMaxHp() * damageHpRatio); globalScene.phaseManager.queueMessage( - i18next.t("arenaTag:stealthRockActivateTrap", { - pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), + i18next.t("arenaTag:stickyWebActivateTrap", { + pokemonName: pokemon.getNameToRender(), }), ); - pokemon.damageAndUpdate(damage, { result: HitResult.INDIRECT }); - pokemon.turnData.damageTaken += damage; - return true; - } - getMatchupScoreMultiplier(pokemon: Pokemon): number { - const damageHpRatio = this.getDamageHpRatio(pokemon); - return Phaser.Math.Linear(super.getMatchupScoreMultiplier(pokemon), 1, 1 - Math.pow(damageHpRatio, damageHpRatio)); + globalScene.phaseManager.unshiftNew( + "StatStageChangePhase", + pokemon.getBattlerIndex(), + false, + [Stat.SPD], + -1, + true, + false, + true, + null, + false, + true, + ); + return true; } } /** - * Arena Tag class for {@link https://bulbapedia.bulbagarden.net/wiki/Sticky_Web_(move) Sticky Web}. - * Applies up to 1 layer of Sticky Web, which lowers the Speed by one stage - * to any Pokémon who is summoned into this trap. + * 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 StickyWebTag extends ArenaTrapTag { - public readonly tagType = ArenaTagType.STICKY_WEB; +class ImprisonTag extends EntryHazardTag { + public readonly tagType = ArenaTagType.IMPRISON; + public override get maxLayers() { + return 1 as const; + } + constructor(sourceId: number | undefined, side: ArenaTagSide) { - super(MoveId.STICKY_WEB, sourceId, side, 1); + super(MoveId.IMPRISON, sourceId, side); } - onAdd(arena: Arena, quiet = false): void { - super.onAdd(arena); + /** + * Apply the effects of Imprison to all opposing on-field Pokemon. + */ + override onAdd(_arena: Arena, quiet = false) { + super.onAdd(_arena, quiet); - // We assume `quiet=true` means "just add the bloody tag no questions asked" - if (quiet) { - return; - } + const party = this.getAffectedPokemon(); + party.forEach(p => { + if (p.isAllowedInBattle()) { + p.addTag(BattlerTagType.IMPRISON, 1, MoveId.IMPRISON, this.sourceId); + } + }); + } + protected override getAddMessage(source: Pokemon): string { + return i18next.t("battlerTags:imprisonOnAdd", { + pokemonNameWithAffix: getPokemonNameWithAffix(source), + }); + } + + /** + * Checks if the source Pokemon is still active on the field + * @param _arena + * @returns `true` if the source of the tag is still active on the field | `false` if not + */ + override lapse(): boolean { const source = this.getSourcePokemon(); - if (!source) { - console.warn(`Failed to get source Pokemon for SpikesTag on add message; id: ${this.sourceId}`); - return; - } - - globalScene.phaseManager.queueMessage( - i18next.t("arenaTag:stickyWebOnAdd", { - moveName: this.getMoveName(), - opponentDesc: source.getOpponentDescriptor(), - }), - ); + return !!source?.isActive(true); } - override activateTrap(pokemon: Pokemon, simulated: boolean): boolean { - if (pokemon.isGrounded()) { - const cancelled = new BooleanHolder(false); - applyAbAttrs("ProtectStatAbAttr", { - pokemon, - cancelled, - stat: Stat.SPD, - stages: -1, - }); - - if (simulated) { - return !cancelled.value; - } - - if (!cancelled.value) { - globalScene.phaseManager.queueMessage( - i18next.t("arenaTag:stickyWebActivateTrap", { - pokemonName: pokemon.getNameToRender(), - }), - ); - const stages = new NumberHolder(-1); - globalScene.phaseManager.unshiftNew( - "StatStageChangePhase", - pokemon.getBattlerIndex(), - false, - [Stat.SPD], - stages.value, - true, - false, - true, - null, - false, - true, - ); - return true; - } + /** + * This applies the effects of Imprison to any opposing Pokemon that switch into the field while the source Pokemon is still active + * @param {Pokemon} pokemon the Pokemon Imprison is applied to + * @returns `true` + */ + override activateTrap(pokemon: Pokemon): boolean { + const source = this.getSourcePokemon(); + if (source?.isActive(true) && pokemon.isAllowedInBattle()) { + pokemon.addTag(BattlerTagType.IMPRISON, 1, MoveId.IMPRISON, this.sourceId); } + return true; + } - return false; + /** + * When the arena tag is removed, it also attempts to remove any related Battler Tags if they haven't already been removed from the affected Pokemon + * @param arena + */ + override onRemove(): void { + const party = this.getAffectedPokemon(); + party.forEach(p => { + p.removeTag(BattlerTagType.IMPRISON); + }); + } +} + +/** + * Abstract base class for all Room {@linkcode ArenaTag}s, characterized by their immediate removal + * upon overlap. + */ +abstract class RoomArenaTag extends SerializableArenaTag { + declare abstract tagType: RoomArenaTagType; + + /** + * Immediately remove this Tag upon overlapping. + * @sealed + */ + override onOverlap(): void { + globalScene.arena.removeTagOnSide(this.tagType, this.side); } } @@ -1099,7 +1175,7 @@ class StickyWebTag extends ArenaTrapTag { * Reverses the Speed stats for all Pokémon on the field as long as this arena tag is up, * also reversing the turn order for all Pokémon on the field as well. */ -export class TrickRoomTag extends SerializableArenaTag { +export class TrickRoomTag extends RoomArenaTag { public readonly tagType = ArenaTagType.TRICK_ROOM; constructor(turnCount: number, sourceId?: number) { super(turnCount, MoveId.TRICK_ROOM, sourceId); @@ -1129,7 +1205,7 @@ export class TrickRoomTag extends SerializableArenaTag { globalScene.phaseManager.queueMessage( i18next.t("arenaTag:trickRoomOnAdd", { - moveName: this.getMoveName(), + pokemonNameWithAffix: getPokemonNameWithAffix(source), }), ); } @@ -1287,75 +1363,6 @@ class NoneTag extends ArenaTag { } } -/** - * 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 { - public readonly tagType = ArenaTagType.IMPRISON; - constructor(sourceId: number | undefined, side: ArenaTagSide) { - super(MoveId.IMPRISON, sourceId, side, 1); - } - - /** - * Apply the effects of Imprison to all opposing on-field Pokemon. - */ - override onAdd() { - const source = this.getSourcePokemon(); - if (!source) { - return; - } - - const party = this.getAffectedPokemon(); - party.forEach(p => { - if (p.isAllowedInBattle()) { - p.addTag(BattlerTagType.IMPRISON, 1, MoveId.IMPRISON, this.sourceId); - } - }); - - globalScene.phaseManager.queueMessage( - i18next.t("battlerTags:imprisonOnAdd", { - pokemonNameWithAffix: getPokemonNameWithAffix(source), - }), - ); - } - - /** - * Checks if the source Pokemon is still active on the field - * @param _arena - * @returns `true` if the source of the tag is still active on the field | `false` if not - */ - override lapse(): boolean { - const source = this.getSourcePokemon(); - return !!source?.isActive(true); - } - - /** - * This applies the effects of Imprison to any opposing Pokemon that switch into the field while the source Pokemon is still active - * @param {Pokemon} pokemon the Pokemon Imprison is applied to - * @returns `true` - */ - override activateTrap(pokemon: Pokemon): boolean { - const source = this.getSourcePokemon(); - if (source?.isActive(true) && pokemon.isAllowedInBattle()) { - pokemon.addTag(BattlerTagType.IMPRISON, 1, MoveId.IMPRISON, this.sourceId); - } - return true; - } - - /** - * When the arena tag is removed, it also attempts to remove any related Battler Tags if they haven't already been removed from the affected Pokemon - * @param arena - */ - override onRemove(): void { - const party = this.getAffectedPokemon(); - party.forEach(p => { - p.removeTag(BattlerTagType.IMPRISON); - }); - } -} - /** * Arena Tag implementing the "sea of fire" effect from the combination * of {@link https://bulbapedia.bulbagarden.net/wiki/Fire_Pledge_(move) | Fire Pledge} diff --git a/src/data/balance/biomes.ts b/src/data/balance/biomes.ts index d8297636393..c0c57cb15fb 100644 --- a/src/data/balance/biomes.ts +++ b/src/data/balance/biomes.ts @@ -7,6 +7,7 @@ import { TimeOfDay } from "#enums/time-of-day"; import { TrainerType } from "#enums/trainer-type"; import { randSeedInt } from "#utils/common"; import { getEnumValues } from "#utils/enums"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; export function getBiomeName(biome: BiomeId | -1) { @@ -15,13 +16,13 @@ export function getBiomeName(biome: BiomeId | -1) { } switch (biome) { case BiomeId.GRASS: - return i18next.t("biome:GRASS"); + return i18next.t("biome:grass"); case BiomeId.RUINS: - return i18next.t("biome:RUINS"); + return i18next.t("biome:ruins"); case BiomeId.END: - return i18next.t("biome:END"); + return i18next.t("biome:end"); default: - return i18next.t(`biome:${BiomeId[biome].toUpperCase()}`); + return i18next.t(`biome:${toCamelCase(BiomeId[biome])}`); } } diff --git a/src/data/balance/egg-moves.ts b/src/data/balance/egg-moves.ts index e936afcdc08..2d2e981219d 100644 --- a/src/data/balance/egg-moves.ts +++ b/src/data/balance/egg-moves.ts @@ -6,7 +6,7 @@ import { toTitleCase } from "#utils/strings"; export const speciesEggMoves = { [SpeciesId.BULBASAUR]: [ MoveId.SAPPY_SEED, MoveId.MALIGNANT_CHAIN, MoveId.EARTH_POWER, MoveId.MATCHA_GOTCHA ], - [SpeciesId.CHARMANDER]: [ MoveId.DRAGON_DANCE, MoveId.BITTER_BLADE, MoveId.EARTH_POWER, MoveId.OBLIVION_WING ], + [SpeciesId.CHARMANDER]: [ MoveId.DRAGON_DANCE, MoveId.AEROBLAST, MoveId.EARTH_POWER, MoveId.BITTER_BLADE ], [SpeciesId.SQUIRTLE]: [ MoveId.FREEZE_DRY, MoveId.ARMOR_CANNON, MoveId.SHORE_UP, MoveId.ORIGIN_PULSE ], [SpeciesId.CATERPIE]: [ MoveId.SANDSEAR_STORM, MoveId.SILK_TRAP, MoveId.TWIN_BEAM, MoveId.BLEAKWIND_STORM ], [SpeciesId.WEEDLE]: [ MoveId.THOUSAND_ARROWS, MoveId.NOXIOUS_TORQUE, MoveId.ATTACK_ORDER, MoveId.VICTORY_DANCE ], @@ -29,7 +29,7 @@ export const speciesEggMoves = { [SpeciesId.GROWLITHE]: [ MoveId.ZING_ZAP, MoveId.DRAGON_DANCE, MoveId.MORNING_SUN, MoveId.SACRED_FIRE ], [SpeciesId.POLIWAG]: [ MoveId.SLACK_OFF, MoveId.WILDBOLT_STORM, MoveId.DRAIN_PUNCH, MoveId.SURGING_STRIKES ], [SpeciesId.ABRA]: [ MoveId.AURA_SPHERE, MoveId.BADDY_BAD, MoveId.ICE_BEAM, MoveId.PSYSTRIKE ], - [SpeciesId.MACHOP]: [ MoveId.COMBAT_TORQUE, MoveId.METEOR_MASH, MoveId.MOUNTAIN_GALE, MoveId.FISSURE ], + [SpeciesId.MACHOP]: [ MoveId.DRAIN_PUNCH, MoveId.METEOR_MASH, MoveId.MOUNTAIN_GALE, MoveId.FISSURE ], [SpeciesId.BELLSPROUT]: [ MoveId.SOLAR_BLADE, MoveId.STRENGTH_SAP, MoveId.FIRE_LASH, MoveId.VICTORY_DANCE ], [SpeciesId.TENTACOOL]: [ MoveId.BANEFUL_BUNKER, MoveId.MALIGNANT_CHAIN, MoveId.BOUNCY_BUBBLE, MoveId.STRENGTH_SAP ], [SpeciesId.GEODUDE]: [ MoveId.FLARE_BLITZ, MoveId.HEAD_SMASH, MoveId.SHORE_UP, MoveId.SHELL_SMASH ], @@ -142,7 +142,7 @@ export const speciesEggMoves = { [SpeciesId.RALTS]: [ MoveId.PSYBLADE, MoveId.BITTER_BLADE, MoveId.NO_RETREAT, MoveId.BOOMBURST ], [SpeciesId.SURSKIT]: [ MoveId.POLLEN_PUFF, MoveId.FIERY_DANCE, MoveId.BOUNCY_BUBBLE, MoveId.AEROBLAST ], [SpeciesId.SHROOMISH]: [ MoveId.ACCELEROCK, MoveId.TRAILBLAZE, MoveId.STORM_THROW, MoveId.SAPPY_SEED ], - [SpeciesId.SLAKOTH]: [ MoveId.CRUSH_GRIP, MoveId.DRAIN_PUNCH, MoveId.PARTING_SHOT, MoveId.SKILL_SWAP ], + [SpeciesId.SLAKOTH]: [ MoveId.ENTRAINMENT, MoveId.DRAIN_PUNCH, MoveId.PARTING_SHOT, MoveId.CRUSH_GRIP ], [SpeciesId.NINCADA]: [ MoveId.BULLDOZE, MoveId.STICKY_WEB, MoveId.SHADOW_BONE, MoveId.SHELL_SMASH ], [SpeciesId.WHISMUR]: [ MoveId.ALLURING_VOICE, MoveId.SHIFT_GEAR, MoveId.SPARKLING_ARIA, MoveId.TORCH_SONG ], [SpeciesId.MAKUHITA]: [ MoveId.COMBAT_TORQUE, MoveId.SLACK_OFF, MoveId.HEAT_CRASH, MoveId.DOUBLE_IRON_BASH ], @@ -229,7 +229,7 @@ export const speciesEggMoves = { [SpeciesId.MIME_JR]: [ MoveId.CHILLY_RECEPTION, MoveId.MOONBLAST, MoveId.FROST_BREATH, MoveId.LUMINA_CRASH ], [SpeciesId.HAPPINY]: [ MoveId.COTTON_GUARD, MoveId.SEISMIC_TOSS, MoveId.SIZZLY_SLIDE, MoveId.REVIVAL_BLESSING ], [SpeciesId.CHATOT]: [ MoveId.SPARKLING_ARIA, MoveId.BOOMBURST, MoveId.BATON_PASS, MoveId.TORCH_SONG ], - [SpeciesId.SPIRITOMB]: [ MoveId.PARTING_SHOT, MoveId.BADDY_BAD, MoveId.STRENGTH_SAP, MoveId.SPECTRAL_THIEF ], + [SpeciesId.SPIRITOMB]: [ MoveId.PARTING_SHOT, MoveId.BADDY_BAD, MoveId.BITTER_MALICE, MoveId.STRENGTH_SAP ], [SpeciesId.GIBLE]: [ MoveId.METEOR_MASH, MoveId.BITTER_BLADE, MoveId.LANDS_WRATH, MoveId.DRAGON_DANCE ], [SpeciesId.MUNCHLAX]: [ MoveId.STUFF_CHEEKS, MoveId.GRAV_APPLE, MoveId.SLACK_OFF, MoveId.EXTREME_SPEED ], [SpeciesId.RIOLU]: [ MoveId.THUNDEROUS_KICK, MoveId.TACHYON_CUTTER, MoveId.TRIPLE_AXEL, MoveId.SUNSTEEL_STRIKE ], @@ -247,7 +247,7 @@ export const speciesEggMoves = { [SpeciesId.DIALGA]: [ MoveId.CORE_ENFORCER, MoveId.TAKE_HEART, MoveId.RECOVER, MoveId.MAKE_IT_RAIN ], [SpeciesId.PALKIA]: [ MoveId.MALIGNANT_CHAIN, MoveId.TAKE_HEART, MoveId.RECOVER, MoveId.ORIGIN_PULSE ], [SpeciesId.HEATRAN]: [ MoveId.ENERGY_BALL, MoveId.RECOVER, MoveId.ERUPTION, MoveId.TACHYON_CUTTER ], - [SpeciesId.REGIGIGAS]: [ MoveId.SKILL_SWAP, MoveId.RECOVER, MoveId.EXTREME_SPEED, MoveId.GIGATON_HAMMER ], + [SpeciesId.REGIGIGAS]: [ MoveId.OBSTRUCT, MoveId.RECOVER, MoveId.STORM_THROW, MoveId.LANDS_WRATH ], [SpeciesId.GIRATINA]: [ MoveId.DRAGON_DANCE, MoveId.SPECTRAL_THIEF, MoveId.RECOVER, MoveId.COLLISION_COURSE ], [SpeciesId.CRESSELIA]: [ MoveId.COSMIC_POWER, MoveId.BODY_PRESS, MoveId.SIZZLY_SLIDE, MoveId.LUMINA_CRASH ], [SpeciesId.PHIONE]: [ MoveId.BOUNCY_BUBBLE, MoveId.FREEZE_DRY, MoveId.STORED_POWER, MoveId.ORIGIN_PULSE ], @@ -318,7 +318,7 @@ export const speciesEggMoves = { [SpeciesId.MIENFOO]: [ MoveId.GUNK_SHOT, MoveId.SUPERCELL_SLAM, MoveId.MOUNTAIN_GALE, MoveId.WICKED_BLOW ], [SpeciesId.DRUDDIGON]: [ MoveId.FIRE_LASH, MoveId.MORNING_SUN, MoveId.DRAGON_DARTS, MoveId.CLANGOROUS_SOUL ], [SpeciesId.GOLETT]: [ MoveId.SHIFT_GEAR, MoveId.DRAIN_PUNCH, MoveId.HEADLONG_RUSH, MoveId.RAGE_FIST ], - [SpeciesId.PAWNIARD]: [ MoveId.SUCKER_PUNCH, MoveId.CEASELESS_EDGE, MoveId.BITTER_BLADE, MoveId.LAST_RESPECTS ], + [SpeciesId.PAWNIARD]: [ MoveId.SUCKER_PUNCH, MoveId.SPIRIT_BREAK, MoveId.LAST_RESPECTS, MoveId.BITTER_BLADE ], [SpeciesId.BOUFFALANT]: [ MoveId.HORN_LEECH, MoveId.HIGH_JUMP_KICK, MoveId.HEAD_SMASH, MoveId.FLARE_BLITZ ], [SpeciesId.RUFFLET]: [ MoveId.FLOATY_FALL, MoveId.AURA_SPHERE, MoveId.NO_RETREAT, MoveId.BOLT_BEAK ], [SpeciesId.VULLABY]: [ MoveId.FOUL_PLAY, MoveId.BODY_PRESS, MoveId.ROOST, MoveId.RUINATION ], @@ -333,7 +333,7 @@ export const speciesEggMoves = { [SpeciesId.THUNDURUS]: [ MoveId.SANDSEAR_STORM, MoveId.HURRICANE, MoveId.FROST_BREATH, MoveId.ELECTRO_SHOT ], [SpeciesId.RESHIRAM]: [ MoveId.ENERGY_BALL, MoveId.TAKE_HEART, MoveId.FICKLE_BEAM, MoveId.ERUPTION ], [SpeciesId.ZEKROM]: [ MoveId.TRIPLE_AXEL, MoveId.THUNDEROUS_KICK, MoveId.DRAGON_HAMMER, MoveId.DRAGON_ENERGY ], - [SpeciesId.LANDORUS]: [ MoveId.STONE_AXE, MoveId.FLOATY_FALL, MoveId.ROOST, MoveId.BLEAKWIND_STORM ], + [SpeciesId.LANDORUS]: [ MoveId.STONE_AXE, MoveId.FLOATY_FALL, MoveId.ROOST, MoveId.THOUSAND_WAVES ], [SpeciesId.KYUREM]: [ MoveId.DRAGON_DARTS, MoveId.GLACIAL_LANCE, MoveId.NO_RETREAT, MoveId.DRAGON_ENERGY ], [SpeciesId.KELDEO]: [ MoveId.BOUNCY_BUBBLE, MoveId.THUNDERBOLT, MoveId.ICE_BEAM, MoveId.STEAM_ERUPTION ], [SpeciesId.MELOETTA]: [ MoveId.BODY_SLAM, MoveId.PSYCHIC_NOISE, MoveId.TRIPLE_ARROWS, MoveId.TORCH_SONG ], @@ -351,7 +351,7 @@ export const speciesEggMoves = { [SpeciesId.PANCHAM]: [ MoveId.DRAIN_PUNCH, MoveId.SUCKER_PUNCH, MoveId.METEOR_MASH, MoveId.WICKED_BLOW ], [SpeciesId.FURFROU]: [ MoveId.TIDY_UP, MoveId.SLACK_OFF, MoveId.COMBAT_TORQUE, MoveId.MULTI_ATTACK ], [SpeciesId.ESPURR]: [ MoveId.LUSTER_PURGE, MoveId.MOONBLAST, MoveId.AURA_SPHERE, MoveId.DARK_VOID ], - [SpeciesId.HONEDGE]: [ MoveId.TACHYON_CUTTER, MoveId.SHADOW_BONE, MoveId.BITTER_BLADE, MoveId.BEHEMOTH_BLADE ], + [SpeciesId.HONEDGE]: [ MoveId.TACHYON_CUTTER, MoveId.SPIRIT_SHACKLE, MoveId.BITTER_BLADE, MoveId.BEHEMOTH_BLADE ], [SpeciesId.SPRITZEE]: [ MoveId.SPEED_SWAP, MoveId.REVIVAL_BLESSING, MoveId.ROOST, MoveId.TORCH_SONG ], [SpeciesId.SWIRLIX]: [ MoveId.BELLY_DRUM, MoveId.HEADLONG_RUSH, MoveId.MAGICAL_TORQUE, MoveId.REVIVAL_BLESSING ], [SpeciesId.INKAY]: [ MoveId.POWER_TRIP, MoveId.SPIN_OUT, MoveId.RECOVER, MoveId.PSYCHO_BOOST ], @@ -429,7 +429,7 @@ export const speciesEggMoves = { [SpeciesId.MAGEARNA]: [ MoveId.STRENGTH_SAP, MoveId.EARTH_POWER, MoveId.MOONBLAST, MoveId.MAKE_IT_RAIN ], [SpeciesId.MARSHADOW]: [ MoveId.POWER_UP_PUNCH, MoveId.BONEMERANG, MoveId.METEOR_MASH, MoveId.TRIPLE_AXEL ], [SpeciesId.POIPOLE]: [ MoveId.MALIGNANT_CHAIN, MoveId.ICE_BEAM, MoveId.ARMOR_CANNON, MoveId.CLANGING_SCALES ], - [SpeciesId.STAKATAKA]: [ MoveId.HEAVY_SLAM, MoveId.SHORE_UP, MoveId.CURSE, MoveId.SALT_CURE ], + [SpeciesId.STAKATAKA]: [ MoveId.HEAVY_SLAM, MoveId.HEAL_ORDER, MoveId.CURSE, MoveId.SALT_CURE ], [SpeciesId.BLACEPHALON]: [ MoveId.STEEL_BEAM, MoveId.MOONBLAST, MoveId.CHLOROBLAST, MoveId.MOONGEIST_BEAM ], [SpeciesId.ZERAORA]: [ MoveId.SWORDS_DANCE, MoveId.FIRE_LASH, MoveId.COLLISION_COURSE, MoveId.TRIPLE_AXEL ], [SpeciesId.MELTAN]: [ MoveId.BULLET_PUNCH, MoveId.DRAIN_PUNCH, MoveId.BULK_UP, MoveId.PLASMA_FISTS ], @@ -482,7 +482,7 @@ export const speciesEggMoves = { [SpeciesId.ZAMAZENTA]: [ MoveId.BULK_UP, MoveId.BODY_PRESS, MoveId.POWER_TRIP, MoveId.SLACK_OFF ], [SpeciesId.ETERNATUS]: [ MoveId.BODY_PRESS, MoveId.NASTY_PLOT, MoveId.MALIGNANT_CHAIN, MoveId.DRAGON_ENERGY ], [SpeciesId.KUBFU]: [ MoveId.METEOR_MASH, MoveId.DRAIN_PUNCH, MoveId.JET_PUNCH, MoveId.DRAGON_DANCE ], - [SpeciesId.ZARUDE]: [ MoveId.SAPPY_SEED, MoveId.MIGHTY_CLEAVE, MoveId.WICKED_BLOW, MoveId.VICTORY_DANCE ], + [SpeciesId.ZARUDE]: [ MoveId.LEAF_BLADE, MoveId.HEADLONG_RUSH, MoveId.WICKED_BLOW, MoveId.VICTORY_DANCE ], [SpeciesId.REGIELEKI]: [ MoveId.NASTY_PLOT, MoveId.ICE_BEAM, MoveId.EARTH_POWER, MoveId.ELECTRO_DRIFT ], [SpeciesId.REGIDRAGO]: [ MoveId.SHELL_SIDE_ARM, MoveId.FLAMETHROWER, MoveId.TAKE_HEART, MoveId.DRAGON_DARTS ], [SpeciesId.GLASTRIER]: [ MoveId.SPEED_SWAP, MoveId.SLACK_OFF, MoveId.HIGH_HORSEPOWER, MoveId.GLACIAL_LANCE ], diff --git a/src/data/balance/passives.ts b/src/data/balance/passives.ts index 64fa9b87138..0e34917fd80 100644 --- a/src/data/balance/passives.ts +++ b/src/data/balance/passives.ts @@ -208,7 +208,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.XATU]: { 0: AbilityId.SHEER_FORCE }, [SpeciesId.MAREEP]: { 0: AbilityId.ELECTROMORPHOSIS }, [SpeciesId.FLAAFFY]: { 0: AbilityId.ELECTROMORPHOSIS }, - [SpeciesId.AMPHAROS]: { 0: AbilityId.ELECTROMORPHOSIS, 1: AbilityId.ELECTROMORPHOSIS }, + [SpeciesId.AMPHAROS]: { 0: AbilityId.ELECTROMORPHOSIS, 1: AbilityId.FLUFFY }, [SpeciesId.HOPPIP]: { 0: AbilityId.WIND_RIDER }, [SpeciesId.SKIPLOOM]: { 0: AbilityId.WIND_RIDER }, [SpeciesId.JUMPLUFF]: { 0: AbilityId.FLUFFY }, @@ -416,8 +416,8 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.REGIROCK]: { 0: AbilityId.SAND_STREAM }, [SpeciesId.REGICE]: { 0: AbilityId.SNOW_WARNING }, [SpeciesId.REGISTEEL]: { 0: AbilityId.STEELY_SPIRIT }, - [SpeciesId.LATIAS]: { 0: AbilityId.SPEED_BOOST, 1: AbilityId.PRISM_ARMOR }, - [SpeciesId.LATIOS]: { 0: AbilityId.SPEED_BOOST, 1: AbilityId.TINTED_LENS }, + [SpeciesId.LATIAS]: { 0: AbilityId.PRISM_ARMOR, 1: AbilityId.PRISM_ARMOR }, + [SpeciesId.LATIOS]: { 0: AbilityId.NEUROFORCE, 1: AbilityId.NEUROFORCE }, [SpeciesId.KYOGRE]: { 0: AbilityId.MOLD_BREAKER, 1: AbilityId.TERAVOLT }, [SpeciesId.GROUDON]: { 0: AbilityId.MOLD_BREAKER, 1: AbilityId.TURBOBLAZE }, [SpeciesId.RAYQUAZA]: { 0: AbilityId.UNNERVE, 1: AbilityId.UNNERVE }, @@ -521,7 +521,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.SHAYMIN]: { 0: AbilityId.GRASSY_SURGE, 1: AbilityId.DELTA_STREAM }, [SpeciesId.ARCEUS]: { 0: AbilityId.ADAPTABILITY, 1: AbilityId.ADAPTABILITY, 2: AbilityId.ADAPTABILITY, 3: AbilityId.ADAPTABILITY, 4: AbilityId.ADAPTABILITY, 5: AbilityId.ADAPTABILITY, 6: AbilityId.ADAPTABILITY, 7: AbilityId.ADAPTABILITY, 8: AbilityId.ADAPTABILITY, 9: AbilityId.ADAPTABILITY, 10: AbilityId.ADAPTABILITY, 11: AbilityId.ADAPTABILITY, 12: AbilityId.ADAPTABILITY, 13: AbilityId.ADAPTABILITY, 14: AbilityId.ADAPTABILITY, 15: AbilityId.ADAPTABILITY, 16: AbilityId.ADAPTABILITY, 17: AbilityId.ADAPTABILITY }, - [SpeciesId.VICTINI]: { 0: AbilityId.SHEER_FORCE }, + [SpeciesId.VICTINI]: { 0: AbilityId.SERENE_GRACE }, [SpeciesId.SNIVY]: { 0: AbilityId.MULTISCALE }, [SpeciesId.SERVINE]: { 0: AbilityId.MULTISCALE }, [SpeciesId.SERPERIOR]: { 0: AbilityId.MULTISCALE }, @@ -585,7 +585,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.KROKOROK]: { 0: AbilityId.TOUGH_CLAWS }, [SpeciesId.KROOKODILE]: { 0: AbilityId.TOUGH_CLAWS }, [SpeciesId.DARUMAKA]: { 0: AbilityId.GORILLA_TACTICS }, - [SpeciesId.DARMANITAN]: { 0: AbilityId.GORILLA_TACTICS, 1: AbilityId.SOLID_ROCK }, + [SpeciesId.DARMANITAN]: { 0: AbilityId.GORILLA_TACTICS, 1: AbilityId.PSYCHIC_SURGE }, [SpeciesId.MARACTUS]: { 0: AbilityId.WELL_BAKED_BODY }, [SpeciesId.DWEBBLE]: { 0: AbilityId.ROCKY_PAYLOAD }, [SpeciesId.CRUSTLE]: { 0: AbilityId.ROCKY_PAYLOAD }, diff --git a/src/data/balance/pokemon-evolutions.ts b/src/data/balance/pokemon-evolutions.ts index 5d3537f4255..d42bce041c2 100644 --- a/src/data/balance/pokemon-evolutions.ts +++ b/src/data/balance/pokemon-evolutions.ts @@ -15,6 +15,7 @@ import type { Pokemon } from "#field/pokemon"; import type { SpeciesStatBoosterItem, SpeciesStatBoosterModifierType } from "#modifiers/modifier-type"; import { coerceArray, isNullOrUndefined, randSeedInt } from "#utils/common"; import { getPokemonSpecies } from "#utils/pokemon-utils"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; export enum SpeciesWildEvolutionDelay { @@ -133,11 +134,11 @@ export class SpeciesEvolutionCondition { case EvoCondKey.FRIENDSHIP: return i18next.t("pokemonEvolutions:friendship"); case EvoCondKey.TIME: - return i18next.t(`pokemonEvolutions:timeOfDay.${TimeOfDay[cond.time[cond.time.length - 1]]}`); // For Day and Night evos, the key we want goes last + return i18next.t(`pokemonEvolutions:timeOfDay.${toCamelCase(TimeOfDay[cond.time[cond.time.length - 1]])}`); // For Day and Night evos, the key we want goes last case EvoCondKey.MOVE_TYPE: - return i18next.t("pokemonEvolutions:moveType", {type: i18next.t(`pokemonInfo:Type.${PokemonType[cond.pkmnType]}`)}); + return i18next.t("pokemonEvolutions:moveType", {type: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[cond.pkmnType])}`)}); case EvoCondKey.PARTY_TYPE: - return i18next.t("pokemonEvolutions:partyType", {type: i18next.t(`pokemonInfo:Type.${PokemonType[cond.pkmnType]}`)}); + return i18next.t("pokemonEvolutions:partyType", {type: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[cond.pkmnType])}`)}); case EvoCondKey.GENDER: return i18next.t("pokemonEvolutions:gender", {gender: getGenderSymbol(cond.gender)}); case EvoCondKey.MOVE: @@ -156,7 +157,7 @@ export class SpeciesEvolutionCondition { case EvoCondKey.SPECIES_CAUGHT: return i18next.t("pokemonEvolutions:caught", {species: getPokemonSpecies(cond.speciesCaught).name}); case EvoCondKey.HELD_ITEM: - return i18next.t(`pokemonEvolutions:heldItem.${cond.itemKey}`); + return i18next.t(`pokemonEvolutions:heldItem.${toCamelCase(cond.itemKey)}`); } }).filter(s => !isNullOrUndefined(s)); // Filter out stringless conditions return this.desc; @@ -245,7 +246,7 @@ export class SpeciesFormEvolution { } if (this.item) { const itemDescription = i18next.t(`modifierType:EvolutionItem.${EvolutionItem[this.item].toUpperCase()}`); - const rarity = this.item > 50 ? i18next.t("pokemonEvolutions:ULTRA") : i18next.t("pokemonEvolutions:GREAT"); + const rarity = this.item > 50 ? i18next.t("pokemonEvolutions:ultra") : i18next.t("pokemonEvolutions:great"); strings.push(i18next.t("pokemonEvolutions:using", {item: itemDescription, tier: rarity})); } if (this.condition) { @@ -651,7 +652,7 @@ export const pokemonEvolutions: PokemonEvolutions = { ], [SpeciesId.KIRLIA]: [ new SpeciesEvolution(SpeciesId.GARDEVOIR, 30, null, null), - new SpeciesEvolution(SpeciesId.GALLADE, 1, EvolutionItem.DAWN_STONE, {key: EvoCondKey.GENDER, gender: Gender.MALE}) + new SpeciesEvolution(SpeciesId.GALLADE, 1, EvolutionItem.DAWN_STONE, {key: EvoCondKey.GENDER, gender: Gender.MALE}, SpeciesWildEvolutionDelay.LONG), ], [SpeciesId.SURSKIT]: [ new SpeciesEvolution(SpeciesId.MASQUERAIN, 22, null, null) @@ -740,7 +741,7 @@ export const pokemonEvolutions: PokemonEvolutions = { ], [SpeciesId.SNORUNT]: [ new SpeciesEvolution(SpeciesId.GLALIE, 42, null, null), - new SpeciesEvolution(SpeciesId.FROSLASS, 1, EvolutionItem.DAWN_STONE, {key: EvoCondKey.GENDER, gender: Gender.FEMALE}) + new SpeciesEvolution(SpeciesId.FROSLASS, 1, EvolutionItem.DAWN_STONE, {key: EvoCondKey.GENDER, gender: Gender.FEMALE}, SpeciesWildEvolutionDelay.LONG), ], [SpeciesId.SPHEAL]: [ new SpeciesEvolution(SpeciesId.SEALEO, 32, null, null) @@ -1590,7 +1591,7 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(SpeciesId.WHIMSICOTT, 1, EvolutionItem.SUN_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [SpeciesId.PETILIL]: [ - new SpeciesEvolution(SpeciesId.HISUI_LILLIGANT, 1, EvolutionItem.SHINY_STONE, null, SpeciesWildEvolutionDelay.LONG), + new SpeciesEvolution(SpeciesId.HISUI_LILLIGANT, 1, EvolutionItem.DAWN_STONE, null, SpeciesWildEvolutionDelay.LONG), new SpeciesEvolution(SpeciesId.LILLIGANT, 1, EvolutionItem.SUN_STONE, null, SpeciesWildEvolutionDelay.LONG) ], [SpeciesId.BASCULIN]: [ diff --git a/src/data/balance/rates.ts b/src/data/balance/rates.ts index c5eaf40e608..06f3ee78efd 100644 --- a/src/data/balance/rates.ts +++ b/src/data/balance/rates.ts @@ -42,10 +42,10 @@ export const SAME_SPECIES_EGG_HA_RATE = 8; export const MANAPHY_EGG_MANAPHY_RATE = 8; export const GACHA_EGG_HA_RATE = 192; -// 1/x for legendary eggs, 1/x*2 for epic eggs, 1/x*4 for rare eggs, and 1/x*8 for common eggs -export const GACHA_DEFAULT_RARE_EGGMOVE_RATE = 6; -export const SAME_SPECIES_EGG_RARE_EGGMOVE_RATE = 3; -export const GACHA_MOVE_UP_RARE_EGGMOVE_RATE = 3; +// Odds are 1/x +// [COMMON, RARE, EPIC/MANAPHY, LEGEND] +export const RARE_EGGMOVE_RATES: readonly number[] = [48, 24, 12, 6]; +export const BOOSTED_RARE_EGGMOVE_RATES: readonly number[] = [16, 12, 6, 3]; // #region Variant properties // The chance x/10 of a shiny being a variant, then of being specifically an epic variant diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 1199ac581a6..104eca0e407 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -50,6 +50,7 @@ import type { } from "#types/battler-tags"; import type { Mutable } from "#types/type-helpers"; import { BooleanHolder, coerceArray, getFrameMs, isNullOrUndefined, NumberHolder, toDmgValue } from "#utils/common"; +import { toCamelCase } from "#utils/strings"; /** * @module @@ -563,7 +564,7 @@ export class BeakBlastChargingTag extends BattlerTag { target: pokemon, }) ) { - phaseData.attacker.trySetStatus(StatusEffect.BURN, true, pokemon); + phaseData.attacker.trySetStatus(StatusEffect.BURN, pokemon); } return true; } @@ -1509,7 +1510,7 @@ export class DrowsyTag extends SerializableBattlerTag { lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { if (!super.lapse(pokemon, lapseType)) { - pokemon.trySetStatus(StatusEffect.SLEEP, true); + pokemon.trySetStatus(StatusEffect.SLEEP); return false; } @@ -1859,7 +1860,7 @@ export class ContactSetStatusProtectedTag extends DamageProtectedTag { * @param user - The pokemon that is being attacked and has the tag */ override onContact(attacker: Pokemon, user: Pokemon): void { - attacker.trySetStatus(this.#statusEffect, true, user); + attacker.trySetStatus(this.#statusEffect, user); } } @@ -2305,7 +2306,7 @@ export class TypeBoostTag extends SerializableBattlerTag { globalScene.phaseManager.queueMessage( i18next.t("abilityTriggers:typeImmunityPowerBoost", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), - typeName: i18next.t(`pokemonInfo:Type.${PokemonType[this.boostedType]}`), + typeName: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[this.boostedType])}`), }), ); } @@ -2330,10 +2331,10 @@ export class CritBoostTag extends SerializableBattlerTag { super.onAdd(pokemon); // Dragon cheer adds +2 crit stages if the pokemon is a Dragon type when the tag is added - if (this.tagType === BattlerTagType.DRAGON_CHEER && pokemon.getTypes(true).includes(PokemonType.DRAGON)) { - (this as Mutable).critStages = 2; - } else { + if (this.tagType === BattlerTagType.DRAGON_CHEER && !pokemon.getTypes(true, true).includes(PokemonType.DRAGON)) { (this as Mutable).critStages = 1; + } else { + (this as Mutable).critStages = 2; } globalScene.phaseManager.queueMessage( @@ -2803,7 +2804,7 @@ export class GulpMissileTag extends SerializableBattlerTag { if (this.tagType === BattlerTagType.GULP_MISSILE_ARROKUDA) { globalScene.phaseManager.unshiftNew("StatStageChangePhase", attacker.getBattlerIndex(), false, [Stat.DEF], -1); } else { - attacker.trySetStatus(StatusEffect.PARALYSIS, true, pokemon); + attacker.trySetStatus(StatusEffect.PARALYSIS, pokemon); } } return false; diff --git a/src/data/berry.ts b/src/data/berry.ts index 61235b75e21..762423799fe 100644 --- a/src/data/berry.ts +++ b/src/data/berry.ts @@ -11,11 +11,11 @@ import { NumberHolder, randSeedInt, toDmgValue } from "#utils/common"; import i18next from "i18next"; export function getBerryName(berryType: BerryType): string { - return i18next.t(`berry:${BerryType[berryType]}.name`); + return i18next.t(`berry:${BerryType[berryType].toLowerCase()}.name`); } export function getBerryEffectDescription(berryType: BerryType): string { - return i18next.t(`berry:${BerryType[berryType]}.effect`); + return i18next.t(`berry:${BerryType[berryType].toLowerCase()}.effect`); } export type BerryPredicate = (pokemon: Pokemon) => boolean; diff --git a/src/data/challenge.ts b/src/data/challenge.ts index 89435149d2f..3c282e7640e 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -1,11 +1,13 @@ import type { FixedBattleConfig } from "#app/battle"; import { getRandomTrainerFunc } from "#app/battle"; -import { defaultStarterSpecies } from "#app/constants"; +import { defaultStarterSpeciesAndEvolutions } from "#app/constants"; import { speciesStarterCosts } from "#balance/starters"; import type { PokemonSpecies } from "#data/pokemon-species"; +import { AbilityAttr } from "#enums/ability-attr"; import { BattleType } from "#enums/battle-type"; import { Challenges } from "#enums/challenges"; import { TypeColor, TypeShadow } from "#enums/color"; +import { DexAttr } from "#enums/dex-attr"; import { ClassicFixedBossWaves } from "#enums/fixed-boss-waves"; import { ModifierTier } from "#enums/modifier-tier"; import { MoveId } from "#enums/move-id"; @@ -19,8 +21,9 @@ import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon"; import { Trainer } from "#field/trainer"; import type { ModifierTypeOption } from "#modifiers/modifier-type"; import { PokemonMove } from "#moves/pokemon-move"; -import type { DexAttrProps, GameData } from "#system/game-data"; +import type { DexAttrProps, GameData, StarterDataEntry } from "#system/game-data"; import { RibbonData, type RibbonFlag } from "#system/ribbons/ribbon-data"; +import type { DexEntry } from "#types/dex-data"; import { type BooleanHolder, isBetween, type NumberHolder, randSeedItem } from "#utils/common"; import { deepCopy } from "#utils/data"; import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils"; @@ -49,7 +52,7 @@ export abstract class Challenge { * @defaultValue 0 */ public get ribbonAwarded(): RibbonFlag { - return 0 as RibbonFlag; + return 0n as RibbonFlag; } /** @@ -237,6 +240,15 @@ export abstract class Challenge { return false; } + /** + * An apply function for STARTER_SELECT_MODIFY challenges. Derived classes should alter this. + * @param _pokemon {@link Pokemon} The starter pokemon to modify. + * @returns {@link boolean} Whether this function did anything. + */ + applyStarterSelectModify(_speciesId: SpeciesId, _dexEntry: DexEntry, _starterDataEntry: StarterDataEntry): boolean { + return false; + } + /** * An apply function for STARTER_MODIFY challenges. Derived classes should alter this. * @param _pokemon {@link Pokemon} The starter pokemon to modify. @@ -436,7 +448,7 @@ export class SingleGenerationChallenge extends Challenge { public override get ribbonAwarded(): RibbonFlag { // NOTE: This logic will not work for the eventual mono gen 10 ribbon, as // as its flag will not be in sequence with the other mono gen ribbons. - return this.value ? ((RibbonData.MONO_GEN_1 << (this.value - 1)) as RibbonFlag) : 0; + return this.value ? ((RibbonData.MONO_GEN_1 << (BigInt(this.value) - 1n)) as RibbonFlag) : 0n; } constructor() { @@ -674,10 +686,10 @@ export class SingleGenerationChallenge extends Challenge { getDescription(overrideValue: number = this.value): string { if (overrideValue === 0) { - return i18next.t("challenges:singleGeneration.desc_default"); + return i18next.t("challenges:singleGeneration.descDefault"); } return i18next.t("challenges:singleGeneration.desc", { - gen: i18next.t(`challenges:singleGeneration.gen_${overrideValue}`), + gen: i18next.t(`challenges:singleGeneration.gen.${overrideValue}`), }); } @@ -706,7 +718,7 @@ export class SingleTypeChallenge extends Challenge { // `this.value` represents the 1-based index of pokemon type // `RibbonData.MONO_NORMAL` starts the flag position for the types, // and we shift it by 1 for the specific type. - return this.value ? ((RibbonData.MONO_NORMAL << (this.value - 1)) as RibbonFlag) : 0; + return this.value ? ((RibbonData.MONO_NORMAL << (BigInt(this.value) - 1n)) as RibbonFlag) : 0n; } private static TYPE_OVERRIDES: monotypeOverride[] = [ { species: SpeciesId.CASTFORM, type: PokemonType.NORMAL, fusion: false }, @@ -756,9 +768,9 @@ export class SingleTypeChallenge extends Challenge { } getDescription(overrideValue: number = this.value): string { - const type = i18next.t(`pokemonInfo:Type.${PokemonType[overrideValue - 1]}`); + const type = i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[overrideValue - 1])}`); const typeColor = `[color=${TypeColor[PokemonType[overrideValue - 1]]}][shadow=${TypeShadow[PokemonType[this.value - 1]]}]${type}[/shadow][/color]`; - const defaultDesc = i18next.t("challenges:singleType.desc_default"); + const defaultDesc = i18next.t("challenges:singleType.descDefault"); const typeDesc = i18next.t("challenges:singleType.desc", { type: typeColor, }); @@ -778,14 +790,14 @@ export class SingleTypeChallenge extends Challenge { */ export class FreshStartChallenge extends Challenge { public override get ribbonAwarded(): RibbonFlag { - return this.value ? RibbonData.FRESH_START : 0; + return this.value ? RibbonData.FRESH_START : 0n; } constructor() { super(Challenges.FRESH_START, 2); } applyStarterChoice(pokemon: PokemonSpecies, valid: BooleanHolder): boolean { - if (this.value === 1 && !defaultStarterSpecies.includes(pokemon.speciesId)) { + if (this.value === 1 && !defaultStarterSpeciesAndEvolutions.includes(pokemon.speciesId)) { valid.value = false; return true; } @@ -797,10 +809,61 @@ export class FreshStartChallenge extends Challenge { return true; } + applyStarterSelectModify(speciesId: SpeciesId, dexEntry: DexEntry, starterDataEntry: StarterDataEntry): boolean { + // Remove all egg moves + starterDataEntry.eggMoves = 0; + + // Remove hidden and passive ability + const defaultAbilities = AbilityAttr.ABILITY_1 | AbilityAttr.ABILITY_2; + starterDataEntry.abilityAttr &= defaultAbilities; + starterDataEntry.passiveAttr = 0; + + // Remove cost reduction + starterDataEntry.valueReduction = 0; + + // Remove natures except for the default ones + const neutralNaturesAttr = + (1 << (Nature.HARDY + 1)) | + (1 << (Nature.DOCILE + 1)) | + (1 << (Nature.SERIOUS + 1)) | + (1 << (Nature.BASHFUL + 1)) | + (1 << (Nature.QUIRKY + 1)); + dexEntry.natureAttr &= neutralNaturesAttr; + + // Cap all ivs at 15 + for (let i = 0; i < 6; i++) { + dexEntry.ivs[i] = Math.min(dexEntry.ivs[i], 15); + } + + // Removes shiny and variants + dexEntry.caughtAttr &= ~DexAttr.SHINY; + dexEntry.caughtAttr &= ~(DexAttr.VARIANT_2 | DexAttr.VARIANT_3); + + // Remove unlocked forms for specific species + if (speciesId === SpeciesId.ZYGARDE) { + // Sets ability from power construct to aura break + const formMask = (DexAttr.DEFAULT_FORM << 2n) - 1n; + dexEntry.caughtAttr &= formMask; + } else if ( + [ + SpeciesId.PIKACHU, + SpeciesId.EEVEE, + SpeciesId.PICHU, + SpeciesId.ROTOM, + SpeciesId.MELOETTA, + SpeciesId.FROAKIE, + ].includes(speciesId) + ) { + const formMask = (DexAttr.DEFAULT_FORM << 1n) - 1n; // These mons are set to form 0 because they're meant to be unlocks or mid-run form changes + dexEntry.caughtAttr &= formMask; + } + + return true; + } + applyStarterModify(pokemon: Pokemon): boolean { pokemon.abilityIndex = pokemon.abilityIndex % 2; // Always base ability, if you set it to hidden it wraps to first ability pokemon.passive = false; // Passive isn't unlocked - pokemon.nature = Nature.HARDY; // Neutral nature let validMoves = pokemon.species .getLevelMoves() .filter(m => isBetween(m[0], 1, 5)) @@ -827,12 +890,14 @@ export class FreshStartChallenge extends Challenge { SpeciesId.ROTOM, SpeciesId.MELOETTA, SpeciesId.FROAKIE, - SpeciesId.ROCKRUFF, ].includes(pokemon.species.speciesId) ) { pokemon.formIndex = 0; // These mons are set to form 0 because they're meant to be unlocks or mid-run form changes } - pokemon.ivs = [15, 15, 15, 15, 15, 15]; // Default IVs of 15 for all stats (Updated to 15 from 10 in 1.2.0) + // Cap all ivs at 15 + for (let i = 0; i < 6; i++) { + pokemon.ivs[i] = Math.min(pokemon.ivs[i], 15); + } pokemon.teraType = pokemon.species.type1; // Always primary tera type return true; } @@ -854,7 +919,7 @@ export class FreshStartChallenge extends Challenge { */ export class InverseBattleChallenge extends Challenge { public override get ribbonAwarded(): RibbonFlag { - return this.value ? RibbonData.INVERSE : 0; + return this.value ? RibbonData.INVERSE : 0n; } constructor() { super(Challenges.INVERSE_BATTLE, 1); @@ -890,7 +955,7 @@ export class InverseBattleChallenge extends Challenge { */ export class FlipStatChallenge extends Challenge { public override get ribbonAwarded(): RibbonFlag { - return this.value ? RibbonData.FLIP_STATS : 0; + return this.value ? RibbonData.FLIP_STATS : 0n; } constructor() { super(Challenges.FLIP_STAT, 1); @@ -973,7 +1038,7 @@ export class LowerStarterPointsChallenge extends Challenge { */ export class LimitedSupportChallenge extends Challenge { public override get ribbonAwarded(): RibbonFlag { - return this.value ? ((RibbonData.NO_HEAL << (this.value - 1)) as RibbonFlag) : 0; + return this.value ? ((RibbonData.NO_HEAL << (BigInt(this.value) - 1n)) as RibbonFlag) : 0n; } constructor() { super(Challenges.LIMITED_SUPPORT, 3); @@ -1008,7 +1073,7 @@ export class LimitedSupportChallenge extends Challenge { */ export class LimitedCatchChallenge extends Challenge { public override get ribbonAwarded(): RibbonFlag { - return this.value ? RibbonData.LIMITED_CATCH : 0; + return this.value ? RibbonData.LIMITED_CATCH : 0n; } constructor() { super(Challenges.LIMITED_CATCH, 1); @@ -1035,7 +1100,7 @@ export class LimitedCatchChallenge extends Challenge { */ export class HardcoreChallenge extends Challenge { public override get ribbonAwarded(): RibbonFlag { - return this.value ? RibbonData.HARDCORE : 0; + return this.value ? RibbonData.HARDCORE : 0n; } constructor() { super(Challenges.HARDCORE, 1); diff --git a/src/data/dialogue.ts b/src/data/dialogue.ts index 361d005e83b..1d672397777 100644 --- a/src/data/dialogue.ts +++ b/src/data/dialogue.ts @@ -85,20 +85,16 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { }, { encounter: [ - "dialogue:breeder_female.encounter.1", - "dialogue:breeder_female.encounter.2", - "dialogue:breeder_female.encounter.3", + "dialogue:breederFemale.encounter.1", + "dialogue:breederFemale.encounter.2", + "dialogue:breederFemale.encounter.3", ], victory: [ - "dialogue:breeder_female.victory.1", - "dialogue:breeder_female.victory.2", - "dialogue:breeder_female.victory.3", - ], - defeat: [ - "dialogue:breeder_female.defeat.1", - "dialogue:breeder_female.defeat.2", - "dialogue:breeder_female.defeat.3", + "dialogue:breederFemale.victory.1", + "dialogue:breederFemale.victory.2", + "dialogue:breederFemale.victory.3", ], + defeat: ["dialogue:breederFemale.defeat.1", "dialogue:breederFemale.defeat.2", "dialogue:breederFemale.defeat.3"], }, ], [TrainerType.FISHERMAN]: [ @@ -108,14 +104,14 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { }, { encounter: [ - "dialogue:fisherman_female.encounter.1", - "dialogue:fisherman_female.encounter.2", - "dialogue:fisherman_female.encounter.3", + "dialogue:fishermanFemale.encounter.1", + "dialogue:fishermanFemale.encounter.2", + "dialogue:fishermanFemale.encounter.3", ], victory: [ - "dialogue:fisherman_female.victory.1", - "dialogue:fisherman_female.victory.2", - "dialogue:fisherman_female.victory.3", + "dialogue:fishermanFemale.victory.1", + "dialogue:fishermanFemale.victory.2", + "dialogue:fishermanFemale.victory.3", ], }, ], @@ -144,29 +140,29 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { [TrainerType.ACE_TRAINER]: [ { encounter: [ - "dialogue:ace_trainer.encounter.1", - "dialogue:ace_trainer.encounter.2", - "dialogue:ace_trainer.encounter.3", - "dialogue:ace_trainer.encounter.4", + "dialogue:aceTrainer.encounter.1", + "dialogue:aceTrainer.encounter.2", + "dialogue:aceTrainer.encounter.3", + "dialogue:aceTrainer.encounter.4", ], victory: [ - "dialogue:ace_trainer.victory.1", - "dialogue:ace_trainer.victory.2", - "dialogue:ace_trainer.victory.3", - "dialogue:ace_trainer.victory.4", + "dialogue:aceTrainer.victory.1", + "dialogue:aceTrainer.victory.2", + "dialogue:aceTrainer.victory.3", + "dialogue:aceTrainer.victory.4", ], defeat: [ - "dialogue:ace_trainer.defeat.1", - "dialogue:ace_trainer.defeat.2", - "dialogue:ace_trainer.defeat.3", - "dialogue:ace_trainer.defeat.4", + "dialogue:aceTrainer.defeat.1", + "dialogue:aceTrainer.defeat.2", + "dialogue:aceTrainer.defeat.3", + "dialogue:aceTrainer.defeat.4", ], }, ], [TrainerType.PARASOL_LADY]: [ { - encounter: ["dialogue:parasol_lady.encounter.1"], - victory: ["dialogue:parasol_lady.victory.1"], + encounter: ["dialogue:parasolLady.encounter.1"], + victory: ["dialogue:parasolLady.victory.1"], }, ], [TrainerType.TWINS]: [ @@ -184,13 +180,13 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { ], [TrainerType.BLACK_BELT]: [ { - encounter: ["dialogue:black_belt.encounter.1", "dialogue:black_belt.encounter.2"], - victory: ["dialogue:black_belt.victory.1", "dialogue:black_belt.victory.2"], + encounter: ["dialogue:blackBelt.encounter.1", "dialogue:blackBelt.encounter.2"], + victory: ["dialogue:blackBelt.victory.1", "dialogue:blackBelt.victory.2"], }, //BATTLE GIRL { - encounter: ["dialogue:battle_girl.encounter.1"], - victory: ["dialogue:battle_girl.victory.1"], + encounter: ["dialogue:battleGirl.encounter.1"], + victory: ["dialogue:battleGirl.victory.1"], }, ], [TrainerType.HIKER]: [ @@ -214,8 +210,8 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { ], [TrainerType.SCHOOL_KID]: [ { - encounter: ["dialogue:school_kid.encounter.1", "dialogue:school_kid.encounter.2"], - victory: ["dialogue:school_kid.victory.1", "dialogue:school_kid.victory.2"], + encounter: ["dialogue:schoolKid.encounter.1", "dialogue:schoolKid.encounter.2"], + victory: ["dialogue:schoolKid.victory.1", "dialogue:schoolKid.victory.2"], }, ], [TrainerType.ARTIST]: [ @@ -236,31 +232,31 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { victory: ["dialogue:worker.victory.1"], }, { - encounter: ["dialogue:worker_female.encounter.1"], - victory: ["dialogue:worker_female.victory.1"], - defeat: ["dialogue:worker_female.defeat.1"], + encounter: ["dialogue:workerFemale.encounter.1"], + victory: ["dialogue:workerFemale.victory.1"], + defeat: ["dialogue:workerFemale.defeat.1"], }, { - encounter: ["dialogue:worker_double.encounter.1"], - victory: ["dialogue:worker_double.victory.1"], + encounter: ["dialogue:workerDouble.encounter.1"], + victory: ["dialogue:workerDouble.victory.1"], }, ], // Defeat dialogue in the language .JSONS exist as translated or placeholders; (en, fr, it, es, de, ja, ko, zh_cn, zh_tw, pt_br) [TrainerType.SNOW_WORKER]: [ { - encounter: ["dialogue:snow_worker.encounter.1"], - victory: ["dialogue:snow_worker.victory.1"], + encounter: ["dialogue:snowWorker.encounter.1"], + victory: ["dialogue:snowWorker.victory.1"], }, { - encounter: ["dialogue:snow_worker_double.encounter.1"], - victory: ["dialogue:snow_worker_double.victory.1"], + encounter: ["dialogue:snowWorkerDouble.encounter.1"], + victory: ["dialogue:snowWorkerDouble.victory.1"], }, ], [TrainerType.HEX_MANIAC]: [ { - encounter: ["dialogue:hex_maniac.encounter.1", "dialogue:hex_maniac.encounter.2"], - victory: ["dialogue:hex_maniac.victory.1", "dialogue:hex_maniac.victory.2"], - defeat: ["dialogue:hex_maniac.defeat.1", "dialogue:hex_maniac.defeat.2"], + encounter: ["dialogue:hexManiac.encounter.1", "dialogue:hexManiac.encounter.2"], + victory: ["dialogue:hexManiac.victory.1", "dialogue:hexManiac.victory.2"], + defeat: ["dialogue:hexManiac.defeat.1", "dialogue:hexManiac.defeat.2"], }, ], [TrainerType.PSYCHIC]: [ @@ -320,15 +316,11 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { }, { encounter: [ - "dialogue:clerk_female.encounter.1", - "dialogue:clerk_female.encounter.2", - "dialogue:clerk_female.encounter.3", - ], - victory: [ - "dialogue:clerk_female.victory.1", - "dialogue:clerk_female.victory.2", - "dialogue:clerk_female.victory.3", + "dialogue:clerkFemale.encounter.1", + "dialogue:clerkFemale.encounter.2", + "dialogue:clerkFemale.encounter.3", ], + victory: ["dialogue:clerkFemale.victory.1", "dialogue:clerkFemale.victory.2", "dialogue:clerkFemale.victory.3"], }, ], [TrainerType.HOOLIGANS]: [ @@ -371,14 +363,14 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { }, { encounter: [ - "dialogue:pokefan_female.encounter.1", - "dialogue:pokefan_female.encounter.2", - "dialogue:pokefan_female.encounter.3", + "dialogue:pokefanFemale.encounter.1", + "dialogue:pokefanFemale.encounter.2", + "dialogue:pokefanFemale.encounter.3", ], victory: [ - "dialogue:pokefan_female.victory.1", - "dialogue:pokefan_female.victory.2", - "dialogue:pokefan_female.victory.3", + "dialogue:pokefanFemale.victory.1", + "dialogue:pokefanFemale.victory.2", + "dialogue:pokefanFemale.victory.3", ], }, ], @@ -389,52 +381,52 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { }, { encounter: [ - "dialogue:rich_female.encounter.1", - "dialogue:rich_female.encounter.2", - "dialogue:rich_female.encounter.3", + "dialogue:richFemale.encounter.1", + "dialogue:richFemale.encounter.2", + "dialogue:richFemale.encounter.3", ], - victory: ["dialogue:rich_female.victory.1", "dialogue:rich_female.victory.2", "dialogue:rich_female.victory.3"], + victory: ["dialogue:richFemale.victory.1", "dialogue:richFemale.victory.2", "dialogue:richFemale.victory.3"], }, ], [TrainerType.RICH_KID]: [ { - encounter: ["dialogue:rich_kid.encounter.1", "dialogue:rich_kid.encounter.2", "dialogue:rich_kid.encounter.3"], + encounter: ["dialogue:richKid.encounter.1", "dialogue:richKid.encounter.2", "dialogue:richKid.encounter.3"], victory: [ - "dialogue:rich_kid.victory.1", - "dialogue:rich_kid.victory.2", - "dialogue:rich_kid.victory.3", - "dialogue:rich_kid.victory.4", + "dialogue:richKid.victory.1", + "dialogue:richKid.victory.2", + "dialogue:richKid.victory.3", + "dialogue:richKid.victory.4", ], }, { encounter: [ - "dialogue:rich_kid_female.encounter.1", - "dialogue:rich_kid_female.encounter.2", - "dialogue:rich_kid_female.encounter.3", + "dialogue:richKidFemale.encounter.1", + "dialogue:richKidFemale.encounter.2", + "dialogue:richKidFemale.encounter.3", ], victory: [ - "dialogue:rich_kid_female.victory.1", - "dialogue:rich_kid_female.victory.2", - "dialogue:rich_kid_female.victory.3", - "dialogue:rich_kid_female.victory.4", + "dialogue:richKidFemale.victory.1", + "dialogue:richKidFemale.victory.2", + "dialogue:richKidFemale.victory.3", + "dialogue:richKidFemale.victory.4", ], }, ], [TrainerType.ROCKET_GRUNT]: [ { encounter: [ - "dialogue:rocket_grunt.encounter.1", - "dialogue:rocket_grunt.encounter.2", - "dialogue:rocket_grunt.encounter.3", - "dialogue:rocket_grunt.encounter.4", - "dialogue:rocket_grunt.encounter.5", + "dialogue:rocketGrunt.encounter.1", + "dialogue:rocketGrunt.encounter.2", + "dialogue:rocketGrunt.encounter.3", + "dialogue:rocketGrunt.encounter.4", + "dialogue:rocketGrunt.encounter.5", ], victory: [ - "dialogue:rocket_grunt.victory.1", - "dialogue:rocket_grunt.victory.2", - "dialogue:rocket_grunt.victory.3", - "dialogue:rocket_grunt.victory.4", - "dialogue:rocket_grunt.victory.5", + "dialogue:rocketGrunt.victory.1", + "dialogue:rocketGrunt.victory.2", + "dialogue:rocketGrunt.victory.3", + "dialogue:rocketGrunt.victory.4", + "dialogue:rocketGrunt.victory.5", ], }, ], @@ -465,18 +457,18 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { [TrainerType.MAGMA_GRUNT]: [ { encounter: [ - "dialogue:magma_grunt.encounter.1", - "dialogue:magma_grunt.encounter.2", - "dialogue:magma_grunt.encounter.3", - "dialogue:magma_grunt.encounter.4", - "dialogue:magma_grunt.encounter.5", + "dialogue:magmaGrunt.encounter.1", + "dialogue:magmaGrunt.encounter.2", + "dialogue:magmaGrunt.encounter.3", + "dialogue:magmaGrunt.encounter.4", + "dialogue:magmaGrunt.encounter.5", ], victory: [ - "dialogue:magma_grunt.victory.1", - "dialogue:magma_grunt.victory.2", - "dialogue:magma_grunt.victory.3", - "dialogue:magma_grunt.victory.4", - "dialogue:magma_grunt.victory.5", + "dialogue:magmaGrunt.victory.1", + "dialogue:magmaGrunt.victory.2", + "dialogue:magmaGrunt.victory.3", + "dialogue:magmaGrunt.victory.4", + "dialogue:magmaGrunt.victory.5", ], }, ], @@ -495,18 +487,18 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { [TrainerType.AQUA_GRUNT]: [ { encounter: [ - "dialogue:aqua_grunt.encounter.1", - "dialogue:aqua_grunt.encounter.2", - "dialogue:aqua_grunt.encounter.3", - "dialogue:aqua_grunt.encounter.4", - "dialogue:aqua_grunt.encounter.5", + "dialogue:aquaGrunt.encounter.1", + "dialogue:aquaGrunt.encounter.2", + "dialogue:aquaGrunt.encounter.3", + "dialogue:aquaGrunt.encounter.4", + "dialogue:aquaGrunt.encounter.5", ], victory: [ - "dialogue:aqua_grunt.victory.1", - "dialogue:aqua_grunt.victory.2", - "dialogue:aqua_grunt.victory.3", - "dialogue:aqua_grunt.victory.4", - "dialogue:aqua_grunt.victory.5", + "dialogue:aquaGrunt.victory.1", + "dialogue:aquaGrunt.victory.2", + "dialogue:aquaGrunt.victory.3", + "dialogue:aquaGrunt.victory.4", + "dialogue:aquaGrunt.victory.5", ], }, ], @@ -525,18 +517,18 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { [TrainerType.GALACTIC_GRUNT]: [ { encounter: [ - "dialogue:galactic_grunt.encounter.1", - "dialogue:galactic_grunt.encounter.2", - "dialogue:galactic_grunt.encounter.3", - "dialogue:galactic_grunt.encounter.4", - "dialogue:galactic_grunt.encounter.5", + "dialogue:galacticGrunt.encounter.1", + "dialogue:galacticGrunt.encounter.2", + "dialogue:galacticGrunt.encounter.3", + "dialogue:galacticGrunt.encounter.4", + "dialogue:galacticGrunt.encounter.5", ], victory: [ - "dialogue:galactic_grunt.victory.1", - "dialogue:galactic_grunt.victory.2", - "dialogue:galactic_grunt.victory.3", - "dialogue:galactic_grunt.victory.4", - "dialogue:galactic_grunt.victory.5", + "dialogue:galacticGrunt.victory.1", + "dialogue:galacticGrunt.victory.2", + "dialogue:galacticGrunt.victory.3", + "dialogue:galacticGrunt.victory.4", + "dialogue:galacticGrunt.victory.5", ], }, ], @@ -561,18 +553,18 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { [TrainerType.PLASMA_GRUNT]: [ { encounter: [ - "dialogue:plasma_grunt.encounter.1", - "dialogue:plasma_grunt.encounter.2", - "dialogue:plasma_grunt.encounter.3", - "dialogue:plasma_grunt.encounter.4", - "dialogue:plasma_grunt.encounter.5", + "dialogue:plasmaGrunt.encounter.1", + "dialogue:plasmaGrunt.encounter.2", + "dialogue:plasmaGrunt.encounter.3", + "dialogue:plasmaGrunt.encounter.4", + "dialogue:plasmaGrunt.encounter.5", ], victory: [ - "dialogue:plasma_grunt.victory.1", - "dialogue:plasma_grunt.victory.2", - "dialogue:plasma_grunt.victory.3", - "dialogue:plasma_grunt.victory.4", - "dialogue:plasma_grunt.victory.5", + "dialogue:plasmaGrunt.victory.1", + "dialogue:plasmaGrunt.victory.2", + "dialogue:plasmaGrunt.victory.3", + "dialogue:plasmaGrunt.victory.4", + "dialogue:plasmaGrunt.victory.5", ], }, ], @@ -591,18 +583,18 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { [TrainerType.FLARE_GRUNT]: [ { encounter: [ - "dialogue:flare_grunt.encounter.1", - "dialogue:flare_grunt.encounter.2", - "dialogue:flare_grunt.encounter.3", - "dialogue:flare_grunt.encounter.4", - "dialogue:flare_grunt.encounter.5", + "dialogue:flareGrunt.encounter.1", + "dialogue:flareGrunt.encounter.2", + "dialogue:flareGrunt.encounter.3", + "dialogue:flareGrunt.encounter.4", + "dialogue:flareGrunt.encounter.5", ], victory: [ - "dialogue:flare_grunt.victory.1", - "dialogue:flare_grunt.victory.2", - "dialogue:flare_grunt.victory.3", - "dialogue:flare_grunt.victory.4", - "dialogue:flare_grunt.victory.5", + "dialogue:flareGrunt.victory.1", + "dialogue:flareGrunt.victory.2", + "dialogue:flareGrunt.victory.3", + "dialogue:flareGrunt.victory.4", + "dialogue:flareGrunt.victory.5", ], }, ], @@ -621,18 +613,18 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { [TrainerType.AETHER_GRUNT]: [ { encounter: [ - "dialogue:aether_grunt.encounter.1", - "dialogue:aether_grunt.encounter.2", - "dialogue:aether_grunt.encounter.3", - "dialogue:aether_grunt.encounter.4", - "dialogue:aether_grunt.encounter.5", + "dialogue:aetherGrunt.encounter.1", + "dialogue:aetherGrunt.encounter.2", + "dialogue:aetherGrunt.encounter.3", + "dialogue:aetherGrunt.encounter.4", + "dialogue:aetherGrunt.encounter.5", ], victory: [ - "dialogue:aether_grunt.victory.1", - "dialogue:aether_grunt.victory.2", - "dialogue:aether_grunt.victory.3", - "dialogue:aether_grunt.victory.4", - "dialogue:aether_grunt.victory.5", + "dialogue:aetherGrunt.victory.1", + "dialogue:aetherGrunt.victory.2", + "dialogue:aetherGrunt.victory.3", + "dialogue:aetherGrunt.victory.4", + "dialogue:aetherGrunt.victory.5", ], }, ], @@ -645,18 +637,18 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { [TrainerType.SKULL_GRUNT]: [ { encounter: [ - "dialogue:skull_grunt.encounter.1", - "dialogue:skull_grunt.encounter.2", - "dialogue:skull_grunt.encounter.3", - "dialogue:skull_grunt.encounter.4", - "dialogue:skull_grunt.encounter.5", + "dialogue:skullGrunt.encounter.1", + "dialogue:skullGrunt.encounter.2", + "dialogue:skullGrunt.encounter.3", + "dialogue:skullGrunt.encounter.4", + "dialogue:skullGrunt.encounter.5", ], victory: [ - "dialogue:skull_grunt.victory.1", - "dialogue:skull_grunt.victory.2", - "dialogue:skull_grunt.victory.3", - "dialogue:skull_grunt.victory.4", - "dialogue:skull_grunt.victory.5", + "dialogue:skullGrunt.victory.1", + "dialogue:skullGrunt.victory.2", + "dialogue:skullGrunt.victory.3", + "dialogue:skullGrunt.victory.4", + "dialogue:skullGrunt.victory.5", ], }, ], @@ -669,18 +661,18 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { [TrainerType.MACRO_GRUNT]: [ { encounter: [ - "dialogue:macro_grunt.encounter.1", - "dialogue:macro_grunt.encounter.2", - "dialogue:macro_grunt.encounter.3", - "dialogue:macro_grunt.encounter.4", - "dialogue:macro_grunt.encounter.5", + "dialogue:macroGrunt.encounter.1", + "dialogue:macroGrunt.encounter.2", + "dialogue:macroGrunt.encounter.3", + "dialogue:macroGrunt.encounter.4", + "dialogue:macroGrunt.encounter.5", ], victory: [ - "dialogue:macro_grunt.victory.1", - "dialogue:macro_grunt.victory.2", - "dialogue:macro_grunt.victory.3", - "dialogue:macro_grunt.victory.4", - "dialogue:macro_grunt.victory.5", + "dialogue:macroGrunt.victory.1", + "dialogue:macroGrunt.victory.2", + "dialogue:macroGrunt.victory.3", + "dialogue:macroGrunt.victory.4", + "dialogue:macroGrunt.victory.5", ], }, ], @@ -693,18 +685,18 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { [TrainerType.STAR_GRUNT]: [ { encounter: [ - "dialogue:star_grunt.encounter.1", - "dialogue:star_grunt.encounter.2", - "dialogue:star_grunt.encounter.3", - "dialogue:star_grunt.encounter.4", - "dialogue:star_grunt.encounter.5", + "dialogue:starGrunt.encounter.1", + "dialogue:starGrunt.encounter.2", + "dialogue:starGrunt.encounter.3", + "dialogue:starGrunt.encounter.4", + "dialogue:starGrunt.encounter.5", ], victory: [ - "dialogue:star_grunt.victory.1", - "dialogue:star_grunt.victory.2", - "dialogue:star_grunt.victory.3", - "dialogue:star_grunt.victory.4", - "dialogue:star_grunt.victory.5", + "dialogue:starGrunt.victory.1", + "dialogue:starGrunt.victory.2", + "dialogue:starGrunt.victory.3", + "dialogue:starGrunt.victory.4", + "dialogue:starGrunt.victory.5", ], }, ], @@ -740,207 +732,207 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { ], [TrainerType.ROCKET_BOSS_GIOVANNI_1]: [ { - encounter: ["dialogue:rocket_boss_giovanni_1.encounter.1"], - victory: ["dialogue:rocket_boss_giovanni_1.victory.1"], - defeat: ["dialogue:rocket_boss_giovanni_1.defeat.1"], + encounter: ["dialogue:rocketBossGiovanni1.encounter.1"], + victory: ["dialogue:rocketBossGiovanni1.victory.1"], + defeat: ["dialogue:rocketBossGiovanni1.defeat.1"], }, ], [TrainerType.ROCKET_BOSS_GIOVANNI_2]: [ { - encounter: ["dialogue:rocket_boss_giovanni_2.encounter.1"], - victory: ["dialogue:rocket_boss_giovanni_2.victory.1"], - defeat: ["dialogue:rocket_boss_giovanni_2.defeat.1"], + encounter: ["dialogue:rocketBossGiovanni2.encounter.1"], + victory: ["dialogue:rocketBossGiovanni2.victory.1"], + defeat: ["dialogue:rocketBossGiovanni2.defeat.1"], }, ], [TrainerType.MAXIE]: [ { - encounter: ["dialogue:magma_boss_maxie_1.encounter.1"], - victory: ["dialogue:magma_boss_maxie_1.victory.1"], - defeat: ["dialogue:magma_boss_maxie_1.defeat.1"], + encounter: ["dialogue:magmaBossMaxie1.encounter.1"], + victory: ["dialogue:magmaBossMaxie1.victory.1"], + defeat: ["dialogue:magmaBossMaxie1.defeat.1"], }, ], [TrainerType.MAXIE_2]: [ { - encounter: ["dialogue:magma_boss_maxie_2.encounter.1"], - victory: ["dialogue:magma_boss_maxie_2.victory.1"], - defeat: ["dialogue:magma_boss_maxie_2.defeat.1"], + encounter: ["dialogue:magmaBossMaxie2.encounter.1"], + victory: ["dialogue:magmaBossMaxie2.victory.1"], + defeat: ["dialogue:magmaBossMaxie2.defeat.1"], }, ], [TrainerType.ARCHIE]: [ { - encounter: ["dialogue:aqua_boss_archie_1.encounter.1"], - victory: ["dialogue:aqua_boss_archie_1.victory.1"], - defeat: ["dialogue:aqua_boss_archie_1.defeat.1"], + encounter: ["dialogue:aquaBossArchie1.encounter.1"], + victory: ["dialogue:aquaBossArchie1.victory.1"], + defeat: ["dialogue:aquaBossArchie1.defeat.1"], }, ], [TrainerType.ARCHIE_2]: [ { - encounter: ["dialogue:aqua_boss_archie_2.encounter.1"], - victory: ["dialogue:aqua_boss_archie_2.victory.1"], - defeat: ["dialogue:aqua_boss_archie_2.defeat.1"], + encounter: ["dialogue:aquaBossArchie2.encounter.1"], + victory: ["dialogue:aquaBossArchie2.victory.1"], + defeat: ["dialogue:aquaBossArchie2.defeat.1"], }, ], [TrainerType.CYRUS]: [ { - encounter: ["dialogue:galactic_boss_cyrus_1.encounter.1"], - victory: ["dialogue:galactic_boss_cyrus_1.victory.1"], - defeat: ["dialogue:galactic_boss_cyrus_1.defeat.1"], + encounter: ["dialogue:galacticBossCyrus1.encounter.1"], + victory: ["dialogue:galacticBossCyrus1.victory.1"], + defeat: ["dialogue:galacticBossCyrus1.defeat.1"], }, ], [TrainerType.CYRUS_2]: [ { - encounter: ["dialogue:galactic_boss_cyrus_2.encounter.1"], - victory: ["dialogue:galactic_boss_cyrus_2.victory.1"], - defeat: ["dialogue:galactic_boss_cyrus_2.defeat.1"], + encounter: ["dialogue:galacticBossCyrus2.encounter.1"], + victory: ["dialogue:galacticBossCyrus2.victory.1"], + defeat: ["dialogue:galacticBossCyrus2.defeat.1"], }, ], [TrainerType.GHETSIS]: [ { - encounter: ["dialogue:plasma_boss_ghetsis_1.encounter.1"], - victory: ["dialogue:plasma_boss_ghetsis_1.victory.1"], - defeat: ["dialogue:plasma_boss_ghetsis_1.defeat.1"], + encounter: ["dialogue:plasmaBossGhetsis1.encounter.1"], + victory: ["dialogue:plasmaBossGhetsis1.victory.1"], + defeat: ["dialogue:plasmaBossGhetsis1.defeat.1"], }, ], [TrainerType.GHETSIS_2]: [ { - encounter: ["dialogue:plasma_boss_ghetsis_2.encounter.1"], - victory: ["dialogue:plasma_boss_ghetsis_2.victory.1"], - defeat: ["dialogue:plasma_boss_ghetsis_2.defeat.1"], + encounter: ["dialogue:plasmaBossGhetsis2.encounter.1"], + victory: ["dialogue:plasmaBossGhetsis2.victory.1"], + defeat: ["dialogue:plasmaBossGhetsis2.defeat.1"], }, ], [TrainerType.LYSANDRE]: [ { - encounter: ["dialogue:flare_boss_lysandre_1.encounter.1"], - victory: ["dialogue:flare_boss_lysandre_1.victory.1"], - defeat: ["dialogue:flare_boss_lysandre_1.defeat.1"], + encounter: ["dialogue:flareBossLysandre1.encounter.1"], + victory: ["dialogue:flareBossLysandre1.victory.1"], + defeat: ["dialogue:flareBossLysandre1.defeat.1"], }, ], [TrainerType.LYSANDRE_2]: [ { - encounter: ["dialogue:flare_boss_lysandre_2.encounter.1"], - victory: ["dialogue:flare_boss_lysandre_2.victory.1"], - defeat: ["dialogue:flare_boss_lysandre_2.defeat.1"], + encounter: ["dialogue:flareBossLysandre2.encounter.1"], + victory: ["dialogue:flareBossLysandre2.victory.1"], + defeat: ["dialogue:flareBossLysandre2.defeat.1"], }, ], [TrainerType.LUSAMINE]: [ { - encounter: ["dialogue:aether_boss_lusamine_1.encounter.1"], - victory: ["dialogue:aether_boss_lusamine_1.victory.1"], - defeat: ["dialogue:aether_boss_lusamine_1.defeat.1"], + encounter: ["dialogue:aetherBossLusamine1.encounter.1"], + victory: ["dialogue:aetherBossLusamine1.victory.1"], + defeat: ["dialogue:aetherBossLusamine1.defeat.1"], }, ], [TrainerType.LUSAMINE_2]: [ { - encounter: ["dialogue:aether_boss_lusamine_2.encounter.1"], - victory: ["dialogue:aether_boss_lusamine_2.victory.1"], - defeat: ["dialogue:aether_boss_lusamine_2.defeat.1"], + encounter: ["dialogue:aetherBossLusamine2.encounter.1"], + victory: ["dialogue:aetherBossLusamine2.victory.1"], + defeat: ["dialogue:aetherBossLusamine2.defeat.1"], }, ], [TrainerType.GUZMA]: [ { - encounter: ["dialogue:skull_boss_guzma_1.encounter.1"], - victory: ["dialogue:skull_boss_guzma_1.victory.1"], - defeat: ["dialogue:skull_boss_guzma_1.defeat.1"], + encounter: ["dialogue:skullBossGuzma1.encounter.1"], + victory: ["dialogue:skullBossGuzma1.victory.1"], + defeat: ["dialogue:skullBossGuzma1.defeat.1"], }, ], [TrainerType.GUZMA_2]: [ { - encounter: ["dialogue:skull_boss_guzma_2.encounter.1"], - victory: ["dialogue:skull_boss_guzma_2.victory.1"], - defeat: ["dialogue:skull_boss_guzma_2.defeat.1"], + encounter: ["dialogue:skullBossGuzma2.encounter.1"], + victory: ["dialogue:skullBossGuzma2.victory.1"], + defeat: ["dialogue:skullBossGuzma2.defeat.1"], }, ], [TrainerType.ROSE]: [ { - encounter: ["dialogue:macro_boss_rose_1.encounter.1"], - victory: ["dialogue:macro_boss_rose_1.victory.1"], - defeat: ["dialogue:macro_boss_rose_1.defeat.1"], + encounter: ["dialogue:macroBossRose1.encounter.1"], + victory: ["dialogue:macroBossRose1.victory.1"], + defeat: ["dialogue:macroBossRose1.defeat.1"], }, ], [TrainerType.ROSE_2]: [ { - encounter: ["dialogue:macro_boss_rose_2.encounter.1"], - victory: ["dialogue:macro_boss_rose_2.victory.1"], - defeat: ["dialogue:macro_boss_rose_2.defeat.1"], + encounter: ["dialogue:macroBossRose2.encounter.1"], + victory: ["dialogue:macroBossRose2.victory.1"], + defeat: ["dialogue:macroBossRose2.defeat.1"], }, ], [TrainerType.PENNY]: [ { - encounter: ["dialogue:star_boss_penny_1.encounter.1"], - victory: ["dialogue:star_boss_penny_1.victory.1"], - defeat: ["dialogue:star_boss_penny_1.defeat.1"], + encounter: ["dialogue:starBossPenny1.encounter.1"], + victory: ["dialogue:starBossPenny1.victory.1"], + defeat: ["dialogue:starBossPenny1.defeat.1"], }, ], [TrainerType.PENNY_2]: [ { - encounter: ["dialogue:star_boss_penny_2.encounter.1"], - victory: ["dialogue:star_boss_penny_2.victory.1"], - defeat: ["dialogue:star_boss_penny_2.defeat.1"], + encounter: ["dialogue:starBossPenny2.encounter.1"], + victory: ["dialogue:starBossPenny2.victory.1"], + defeat: ["dialogue:starBossPenny2.defeat.1"], }, ], [TrainerType.BUCK]: [ { - encounter: ["dialogue:stat_trainer_buck.encounter.1", "dialogue:stat_trainer_buck.encounter.2"], - victory: ["dialogue:stat_trainer_buck.victory.1", "dialogue:stat_trainer_buck.victory.2"], - defeat: ["dialogue:stat_trainer_buck.defeat.1", "dialogue:stat_trainer_buck.defeat.2"], + encounter: ["dialogue:statTrainerBuck.encounter.1", "dialogue:statTrainerBuck.encounter.2"], + victory: ["dialogue:statTrainerBuck.victory.1", "dialogue:statTrainerBuck.victory.2"], + defeat: ["dialogue:statTrainerBuck.defeat.1", "dialogue:statTrainerBuck.defeat.2"], }, ], [TrainerType.CHERYL]: [ { - encounter: ["dialogue:stat_trainer_cheryl.encounter.1", "dialogue:stat_trainer_cheryl.encounter.2"], - victory: ["dialogue:stat_trainer_cheryl.victory.1", "dialogue:stat_trainer_cheryl.victory.2"], - defeat: ["dialogue:stat_trainer_cheryl.defeat.1", "dialogue:stat_trainer_cheryl.defeat.2"], + encounter: ["dialogue:statTrainerCheryl.encounter.1", "dialogue:statTrainerCheryl.encounter.2"], + victory: ["dialogue:statTrainerCheryl.victory.1", "dialogue:statTrainerCheryl.victory.2"], + defeat: ["dialogue:statTrainerCheryl.defeat.1", "dialogue:statTrainerCheryl.defeat.2"], }, ], [TrainerType.MARLEY]: [ { - encounter: ["dialogue:stat_trainer_marley.encounter.1", "dialogue:stat_trainer_marley.encounter.2"], - victory: ["dialogue:stat_trainer_marley.victory.1", "dialogue:stat_trainer_marley.victory.2"], - defeat: ["dialogue:stat_trainer_marley.defeat.1", "dialogue:stat_trainer_marley.defeat.2"], + encounter: ["dialogue:statTrainerMarley.encounter.1", "dialogue:statTrainerMarley.encounter.2"], + victory: ["dialogue:statTrainerMarley.victory.1", "dialogue:statTrainerMarley.victory.2"], + defeat: ["dialogue:statTrainerMarley.defeat.1", "dialogue:statTrainerMarley.defeat.2"], }, ], [TrainerType.MIRA]: [ { - encounter: ["dialogue:stat_trainer_mira.encounter.1", "dialogue:stat_trainer_mira.encounter.2"], - victory: ["dialogue:stat_trainer_mira.victory.1", "dialogue:stat_trainer_mira.victory.2"], - defeat: ["dialogue:stat_trainer_mira.defeat.1", "dialogue:stat_trainer_mira.defeat.2"], + encounter: ["dialogue:statTrainerMira.encounter.1", "dialogue:statTrainerMira.encounter.2"], + victory: ["dialogue:statTrainerMira.victory.1", "dialogue:statTrainerMira.victory.2"], + defeat: ["dialogue:statTrainerMira.defeat.1", "dialogue:statTrainerMira.defeat.2"], }, ], [TrainerType.RILEY]: [ { - encounter: ["dialogue:stat_trainer_riley.encounter.1", "dialogue:stat_trainer_riley.encounter.2"], - victory: ["dialogue:stat_trainer_riley.victory.1", "dialogue:stat_trainer_riley.victory.2"], - defeat: ["dialogue:stat_trainer_riley.defeat.1", "dialogue:stat_trainer_riley.defeat.2"], + encounter: ["dialogue:statTrainerRiley.encounter.1", "dialogue:statTrainerRiley.encounter.2"], + victory: ["dialogue:statTrainerRiley.victory.1", "dialogue:statTrainerRiley.victory.2"], + defeat: ["dialogue:statTrainerRiley.defeat.1", "dialogue:statTrainerRiley.defeat.2"], }, ], [TrainerType.VICTOR]: [ { - encounter: ["dialogue:winstrates_victor.encounter.1"], - victory: ["dialogue:winstrates_victor.victory.1"], + encounter: ["dialogue:winstratesVictor.encounter.1"], + victory: ["dialogue:winstratesVictor.victory.1"], }, ], [TrainerType.VICTORIA]: [ { - encounter: ["dialogue:winstrates_victoria.encounter.1"], - victory: ["dialogue:winstrates_victoria.victory.1"], + encounter: ["dialogue:winstratesVictoria.encounter.1"], + victory: ["dialogue:winstratesVictoria.victory.1"], }, ], [TrainerType.VIVI]: [ { - encounter: ["dialogue:winstrates_vivi.encounter.1"], - victory: ["dialogue:winstrates_vivi.victory.1"], + encounter: ["dialogue:winstratesVivi.encounter.1"], + victory: ["dialogue:winstratesVivi.victory.1"], }, ], [TrainerType.VICKY]: [ { - encounter: ["dialogue:winstrates_vicky.encounter.1"], - victory: ["dialogue:winstrates_vicky.victory.1"], + encounter: ["dialogue:winstratesVicky.encounter.1"], + victory: ["dialogue:winstratesVicky.victory.1"], }, ], [TrainerType.VITO]: [ { - encounter: ["dialogue:winstrates_vito.encounter.1"], - victory: ["dialogue:winstrates_vito.victory.1"], + encounter: ["dialogue:winstratesVito.encounter.1"], + victory: ["dialogue:winstratesVito.victory.1"], }, ], [TrainerType.BROCK]: { @@ -954,9 +946,9 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { defeat: ["dialogue:misty.defeat.1", "dialogue:misty.defeat.2", "dialogue:misty.defeat.3"], }, [TrainerType.LT_SURGE]: { - encounter: ["dialogue:lt_surge.encounter.1", "dialogue:lt_surge.encounter.2", "dialogue:lt_surge.encounter.3"], - victory: ["dialogue:lt_surge.victory.1", "dialogue:lt_surge.victory.2", "dialogue:lt_surge.victory.3"], - defeat: ["dialogue:lt_surge.defeat.1", "dialogue:lt_surge.defeat.2", "dialogue:lt_surge.defeat.3"], + encounter: ["dialogue:ltSurge.encounter.1", "dialogue:ltSurge.encounter.2", "dialogue:ltSurge.encounter.3"], + victory: ["dialogue:ltSurge.victory.1", "dialogue:ltSurge.victory.2", "dialogue:ltSurge.victory.3"], + defeat: ["dialogue:ltSurge.defeat.1", "dialogue:ltSurge.defeat.2", "dialogue:ltSurge.defeat.3"], }, [TrainerType.ERIKA]: { encounter: [ @@ -1055,12 +1047,12 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { }, [TrainerType.CRASHER_WAKE]: { encounter: [ - "dialogue:crasher_wake.encounter.1", - "dialogue:crasher_wake.encounter.2", - "dialogue:crasher_wake.encounter.3", + "dialogue:crasherWake.encounter.1", + "dialogue:crasherWake.encounter.2", + "dialogue:crasherWake.encounter.3", ], - victory: ["dialogue:crasher_wake.victory.1", "dialogue:crasher_wake.victory.2", "dialogue:crasher_wake.victory.3"], - defeat: ["dialogue:crasher_wake.defeat.1", "dialogue:crasher_wake.defeat.2", "dialogue:crasher_wake.defeat.3"], + victory: ["dialogue:crasherWake.victory.1", "dialogue:crasherWake.victory.2", "dialogue:crasherWake.victory.3"], + defeat: ["dialogue:crasherWake.defeat.1", "dialogue:crasherWake.defeat.2", "dialogue:crasherWake.defeat.3"], }, [TrainerType.FALKNER]: { encounter: ["dialogue:falkner.encounter.1", "dialogue:falkner.encounter.2", "dialogue:falkner.encounter.3"], @@ -1354,9 +1346,9 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { defeat: ["dialogue:acerola.defeat.1"], }, [TrainerType.LARRY_ELITE]: { - encounter: ["dialogue:larry_elite.encounter.1"], - victory: ["dialogue:larry_elite.victory.1"], - defeat: ["dialogue:larry_elite.defeat.1"], + encounter: ["dialogue:larryElite.encounter.1"], + victory: ["dialogue:larryElite.victory.1"], + defeat: ["dialogue:larryElite.defeat.1"], }, [TrainerType.LANCE]: { encounter: ["dialogue:lance.encounter.1", "dialogue:lance.encounter.2"], @@ -1414,9 +1406,9 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { defeat: ["dialogue:jasmine.defeat.1"], }, [TrainerType.LANCE_CHAMPION]: { - encounter: ["dialogue:lance_champion.encounter.1"], - victory: ["dialogue:lance_champion.victory.1"], - defeat: ["dialogue:lance_champion.defeat.1"], + encounter: ["dialogue:lanceChampion.encounter.1"], + victory: ["dialogue:lanceChampion.victory.1"], + defeat: ["dialogue:lanceChampion.defeat.1"], }, [TrainerType.STEVEN]: { encounter: ["dialogue:steven.encounter.1"], @@ -1624,29 +1616,29 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { defeat: ["dialogue:grusha.defeat.1"], }, [TrainerType.MARNIE_ELITE]: { - encounter: ["dialogue:marnie_elite.encounter.1", "dialogue:marnie_elite.encounter.2"], - victory: ["dialogue:marnie_elite.victory.1", "dialogue:marnie_elite.victory.2"], - defeat: ["dialogue:marnie_elite.defeat.1", "dialogue:marnie_elite.defeat.2"], + encounter: ["dialogue:marnieElite.encounter.1", "dialogue:marnieElite.encounter.2"], + victory: ["dialogue:marnieElite.victory.1", "dialogue:marnieElite.victory.2"], + defeat: ["dialogue:marnieElite.defeat.1", "dialogue:marnieElite.defeat.2"], }, [TrainerType.NESSA_ELITE]: { - encounter: ["dialogue:nessa_elite.encounter.1", "dialogue:nessa_elite.encounter.2"], - victory: ["dialogue:nessa_elite.victory.1", "dialogue:nessa_elite.victory.2"], - defeat: ["dialogue:nessa_elite.defeat.1", "dialogue:nessa_elite.defeat.2"], + encounter: ["dialogue:nessaElite.encounter.1", "dialogue:nessaElite.encounter.2"], + victory: ["dialogue:nessaElite.victory.1", "dialogue:nessaElite.victory.2"], + defeat: ["dialogue:nessaElite.defeat.1", "dialogue:nessaElite.defeat.2"], }, [TrainerType.BEA_ELITE]: { - encounter: ["dialogue:bea_elite.encounter.1", "dialogue:bea_elite.encounter.2"], - victory: ["dialogue:bea_elite.victory.1", "dialogue:bea_elite.victory.2"], - defeat: ["dialogue:bea_elite.defeat.1", "dialogue:bea_elite.defeat.2"], + encounter: ["dialogue:beaElite.encounter.1", "dialogue:beaElite.encounter.2"], + victory: ["dialogue:beaElite.victory.1", "dialogue:beaElite.victory.2"], + defeat: ["dialogue:beaElite.defeat.1", "dialogue:beaElite.defeat.2"], }, [TrainerType.ALLISTER_ELITE]: { - encounter: ["dialogue:allister_elite.encounter.1", "dialogue:allister_elite.encounter.2"], - victory: ["dialogue:allister_elite.victory.1", "dialogue:allister_elite.victory.2"], - defeat: ["dialogue:allister_elite.defeat.1", "dialogue:allister_elite.defeat.2"], + encounter: ["dialogue:allisterElite.encounter.1", "dialogue:allisterElite.encounter.2"], + victory: ["dialogue:allisterElite.victory.1", "dialogue:allisterElite.victory.2"], + defeat: ["dialogue:allisterElite.defeat.1", "dialogue:allisterElite.defeat.2"], }, [TrainerType.RAIHAN_ELITE]: { - encounter: ["dialogue:raihan_elite.encounter.1", "dialogue:raihan_elite.encounter.2"], - victory: ["dialogue:raihan_elite.victory.1", "dialogue:raihan_elite.victory.2"], - defeat: ["dialogue:raihan_elite.defeat.1", "dialogue:raihan_elite.defeat.2"], + encounter: ["dialogue:raihanElite.encounter.1", "dialogue:raihanElite.encounter.2"], + victory: ["dialogue:raihanElite.victory.1", "dialogue:raihanElite.victory.2"], + defeat: ["dialogue:raihanElite.defeat.1", "dialogue:raihanElite.defeat.2"], }, [TrainerType.ALDER]: { encounter: ["dialogue:alder.encounter.1"], @@ -1664,62 +1656,62 @@ export const trainerTypeDialogue: TrainerTypeDialogue = { victory: ["dialogue:rival.victory.1"], }, { - encounter: ["dialogue:rival_female.encounter.1"], - victory: ["dialogue:rival_female.victory.1"], + encounter: ["dialogue:rivalFemale.encounter.1"], + victory: ["dialogue:rivalFemale.victory.1"], }, ], [TrainerType.RIVAL_2]: [ { - encounter: ["dialogue:rival_2.encounter.1"], - victory: ["dialogue:rival_2.victory.1"], + encounter: ["dialogue:rival2.encounter.1"], + victory: ["dialogue:rival2.victory.1"], }, { - encounter: ["dialogue:rival_2_female.encounter.1"], - victory: ["dialogue:rival_2_female.victory.1"], - defeat: ["dialogue:rival_2_female.defeat.1"], + encounter: ["dialogue:rival2Female.encounter.1"], + victory: ["dialogue:rival2Female.victory.1"], + defeat: ["dialogue:rival2Female.defeat.1"], }, ], [TrainerType.RIVAL_3]: [ { - encounter: ["dialogue:rival_3.encounter.1"], - victory: ["dialogue:rival_3.victory.1"], + encounter: ["dialogue:rival3.encounter.1"], + victory: ["dialogue:rival3.victory.1"], }, { - encounter: ["dialogue:rival_3_female.encounter.1"], - victory: ["dialogue:rival_3_female.victory.1"], - defeat: ["dialogue:rival_3_female.defeat.1"], + encounter: ["dialogue:rival3Female.encounter.1"], + victory: ["dialogue:rival3Female.victory.1"], + defeat: ["dialogue:rival3Female.defeat.1"], }, ], [TrainerType.RIVAL_4]: [ { - encounter: ["dialogue:rival_4.encounter.1"], - victory: ["dialogue:rival_4.victory.1"], + encounter: ["dialogue:rival4.encounter.1"], + victory: ["dialogue:rival4.victory.1"], }, { - encounter: ["dialogue:rival_4_female.encounter.1"], - victory: ["dialogue:rival_4_female.victory.1"], - defeat: ["dialogue:rival_4_female.defeat.1"], + encounter: ["dialogue:rival4Female.encounter.1"], + victory: ["dialogue:rival4Female.victory.1"], + defeat: ["dialogue:rival4Female.defeat.1"], }, ], [TrainerType.RIVAL_5]: [ { - encounter: ["dialogue:rival_5.encounter.1"], - victory: ["dialogue:rival_5.victory.1"], + encounter: ["dialogue:rival5.encounter.1"], + victory: ["dialogue:rival5.victory.1"], }, { - encounter: ["dialogue:rival_5_female.encounter.1"], - victory: ["dialogue:rival_5_female.victory.1"], - defeat: ["dialogue:rival_5_female.defeat.1"], + encounter: ["dialogue:rival5Female.encounter.1"], + victory: ["dialogue:rival5Female.victory.1"], + defeat: ["dialogue:rival5Female.defeat.1"], }, ], [TrainerType.RIVAL_6]: [ { - encounter: ["dialogue:rival_6.encounter.1"], - victory: ["dialogue:rival_6.victory.1"], + encounter: ["dialogue:rival6.encounter.1"], + victory: ["dialogue:rival6.victory.1"], }, { - encounter: ["dialogue:rival_6_female.encounter.1"], - victory: ["dialogue:rival_6_female.victory.1"], + encounter: ["dialogue:rival6Female.encounter.1"], + victory: ["dialogue:rival6Female.victory.1"], }, ], }; diff --git a/src/data/double-battle-dialogue.ts b/src/data/double-battle-dialogue.ts index f15b74e4729..d4deee62037 100644 --- a/src/data/double-battle-dialogue.ts +++ b/src/data/double-battle-dialogue.ts @@ -2,43 +2,43 @@ // that caused this to be moved out in the first place export const doubleBattleDialogue = { blue_red_double: { - encounter: ["doubleBattleDialogue:blue_red_double.encounter.1"], - victory: ["doubleBattleDialogue:blue_red_double.victory.1"], + encounter: ["doubleBattleDialogue:blueRedDouble.encounter.1"], + victory: ["doubleBattleDialogue:blueRedDouble.victory.1"], }, red_blue_double: { - encounter: ["doubleBattleDialogue:red_blue_double.encounter.1"], - victory: ["doubleBattleDialogue:red_blue_double.victory.1"], + encounter: ["doubleBattleDialogue:redBlueDouble.encounter.1"], + victory: ["doubleBattleDialogue:redBlueDouble.victory.1"], }, tate_liza_double: { - encounter: ["doubleBattleDialogue:tate_liza_double.encounter.1"], - victory: ["doubleBattleDialogue:tate_liza_double.victory.1"], + encounter: ["doubleBattleDialogue:tateLizaDouble.encounter.1"], + victory: ["doubleBattleDialogue:tateLizaDouble.victory.1"], }, liza_tate_double: { - encounter: ["doubleBattleDialogue:liza_tate_double.encounter.1"], - victory: ["doubleBattleDialogue:liza_tate_double.victory.1"], + encounter: ["doubleBattleDialogue:lizaTateDouble.encounter.1"], + victory: ["doubleBattleDialogue:lizaTateDouble.victory.1"], }, wallace_steven_double: { - encounter: ["doubleBattleDialogue:wallace_steven_double.encounter.1"], - victory: ["doubleBattleDialogue:wallace_steven_double.victory.1"], + encounter: ["doubleBattleDialogue:wallaceStevenDouble.encounter.1"], + victory: ["doubleBattleDialogue:wallaceStevenDouble.victory.1"], }, steven_wallace_double: { - encounter: ["doubleBattleDialogue:steven_wallace_double.encounter.1"], - victory: ["doubleBattleDialogue:steven_wallace_double.victory.1"], + encounter: ["doubleBattleDialogue:stevenWallaceDouble.encounter.1"], + victory: ["doubleBattleDialogue:stevenWallaceDouble.victory.1"], }, alder_iris_double: { - encounter: ["doubleBattleDialogue:alder_iris_double.encounter.1"], - victory: ["doubleBattleDialogue:alder_iris_double.victory.1"], + encounter: ["doubleBattleDialogue:alderIrisDouble.encounter.1"], + victory: ["doubleBattleDialogue:alderIrisDouble.victory.1"], }, iris_alder_double: { - encounter: ["doubleBattleDialogue:iris_alder_double.encounter.1"], - victory: ["doubleBattleDialogue:iris_alder_double.victory.1"], + encounter: ["doubleBattleDialogue:irisAlderDouble.encounter.1"], + victory: ["doubleBattleDialogue:irisAlderDouble.victory.1"], }, marnie_piers_double: { - encounter: ["doubleBattleDialogue:marnie_piers_double.encounter.1"], - victory: ["doubleBattleDialogue:marnie_piers_double.victory.1"], + encounter: ["doubleBattleDialogue:marniePiersDouble.encounter.1"], + victory: ["doubleBattleDialogue:marniePiersDouble.victory.1"], }, piers_marnie_double: { - encounter: ["doubleBattleDialogue:piers_marnie_double.encounter.1"], - victory: ["doubleBattleDialogue:piers_marnie_double.victory.1"], + encounter: ["doubleBattleDialogue:piersMarnieDouble.encounter.1"], + victory: ["doubleBattleDialogue:piersMarnieDouble.victory.1"], }, }; diff --git a/src/data/egg.ts b/src/data/egg.ts index 2c567686fc2..5fab276f327 100644 --- a/src/data/egg.ts +++ b/src/data/egg.ts @@ -3,17 +3,16 @@ import { globalScene } from "#app/global-scene"; import Overrides from "#app/overrides"; import { pokemonPrevolutions } from "#balance/pokemon-evolutions"; import { + BOOSTED_RARE_EGGMOVE_RATES, EGG_PITY_EPIC_THRESHOLD, EGG_PITY_LEGENDARY_THRESHOLD, EGG_PITY_RARE_THRESHOLD, GACHA_DEFAULT_COMMON_EGG_THRESHOLD, GACHA_DEFAULT_EPIC_EGG_THRESHOLD, GACHA_DEFAULT_RARE_EGG_THRESHOLD, - GACHA_DEFAULT_RARE_EGGMOVE_RATE, GACHA_DEFAULT_SHINY_RATE, GACHA_EGG_HA_RATE, GACHA_LEGENDARY_UP_THRESHOLD_OFFSET, - GACHA_MOVE_UP_RARE_EGGMOVE_RATE, GACHA_SHINY_UP_SHINY_RATE, HATCH_WAVES_COMMON_EGG, HATCH_WAVES_EPIC_EGG, @@ -21,8 +20,8 @@ import { HATCH_WAVES_MANAPHY_EGG, HATCH_WAVES_RARE_EGG, MANAPHY_EGG_MANAPHY_RATE, + RARE_EGGMOVE_RATES, SAME_SPECIES_EGG_HA_RATE, - SAME_SPECIES_EGG_RARE_EGGMOVE_RATE, SAME_SPECIES_EGG_SHINY_RATE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE, @@ -355,21 +354,22 @@ export class Egg { // #region Private methods //// + /** + * Rolls which egg move slot the egg will have. + * 1/x chance for rare, (x-1)/3 chance for each common move. + * x is determined by Egg Tier. Boosted rates used for eggs obtained through Move Up Gacha and Candy. + * @returns the slot for the egg move + */ 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; + const tierNum = this.isManaphyEgg() ? 2 : this.tier; + let baseChance: number; + if (this._sourceType === EggSourceType.SAME_SPECIES_EGG || this._sourceType === EggSourceType.GACHA_MOVE) { + baseChance = BOOSTED_RARE_EGGMOVE_RATES[tierNum]; + } else { + baseChance = RARE_EGGMOVE_RATES[tierNum]; } - const tierMultiplier = this.isManaphyEgg() ? 2 : Math.pow(2, 3 - this.tier); - return randSeedInt(baseChance * tierMultiplier) ? randSeedInt(3) : 3; + return randSeedInt(baseChance) ? randSeedInt(3) : 3; } private getEggTierDefaultHatchWaves(eggTier?: EggTier): number { diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 8aff2729bd7..ebaf5e03322 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -7,7 +7,7 @@ import { loggedInUser } from "#app/account"; import type { GameMode } from "#app/game-mode"; import { globalScene } from "#app/global-scene"; import { getPokemonNameWithAffix } from "#app/messages"; -import type { ArenaTrapTag } from "#data/arena-tag"; +import type { EntryHazardTag } from "#data/arena-tag"; import { WeakenMoveTypeTag } from "#data/arena-tag"; import { MoveChargeAnim } from "#data/battle-anims"; import { @@ -89,7 +89,7 @@ import type { AttackMoveResult } from "#types/attack-move-result"; import type { Localizable } from "#types/locales"; import type { ChargingMove, MoveAttrMap, MoveAttrString, MoveClassMap, MoveKindString, MoveMessageFunc } from "#types/move-types"; import type { TurnMove } from "#types/turn-move"; -import { BooleanHolder, type Constructor, isNullOrUndefined, NumberHolder, randSeedFloat, randSeedInt, randSeedItem, toDmgValue } from "#utils/common"; +import { BooleanHolder, coerceArray, type Constructor, isNullOrUndefined, NumberHolder, randSeedFloat, randSeedInt, randSeedItem, toDmgValue } from "#utils/common"; import { getEnumValues } from "#utils/enums"; import { toCamelCase, toTitleCase } from "#utils/strings"; import i18next from "i18next"; @@ -1191,8 +1191,9 @@ export abstract class MoveAttr { } /** - * @virtual - * @returns the {@linkcode MoveCondition} or {@linkcode MoveConditionFunc} for this {@linkcode Move} + * Return this `MoveAttr`'s associated {@linkcode MoveCondition} or {@linkcode MoveConditionFunc}. + * The specified condition will be added to all {@linkcode Move}s with this attribute, + * and moves **will fail upon use** if _at least 1_ of their attached conditions returns `false`. */ getCondition(): MoveCondition | MoveConditionFunc | null { return null; @@ -1305,14 +1306,19 @@ export class MoveEffectAttr extends MoveAttr { } /** - * Determines whether the {@linkcode Move}'s effects are valid to {@linkcode apply} - * @virtual - * @param user {@linkcode Pokemon} using the move - * @param target {@linkcode Pokemon} target of the move - * @param move {@linkcode Move} with this attribute - * @param args Set of unique arguments needed by this attribute - * @returns true if basic application of the ability attribute should be possible + * Determine whether this {@linkcode MoveAttr}'s effects are able to {@linkcode apply | be applied} to the target. + * + * Will **NOT** cause the move to fail upon returning `false` (unlike {@linkcode getCondition}; + * merely that the effect for this attribute will be nullified. + * @param user - The {@linkcode Pokemon} using the move + * @param target - The {@linkcode Pokemon} being targeted by the move, or {@linkcode user} if the move is + * {@linkcode selfTarget | self-targeting} + * @param move - The {@linkcode Move} being used + * @param _args - Set of unique arguments needed by this attribute + * @returns `true` if basic application of this `MoveAttr`s effects should be possible */ + // TODO: Decouple this check from the `apply` step + // TODO: Make non-damaging moves fail by default if none of their attributes can apply canApply(user: Pokemon, target: Pokemon, move: Move, _args?: any[]) { return !(this.selfTarget ? user : target).isFainted(); } @@ -1960,19 +1966,17 @@ export class AddSubstituteAttr extends MoveEffectAttr { * @see {@linkcode apply} */ export class HealAttr extends MoveEffectAttr { - /** The percentage of {@linkcode Stat.HP} to heal */ - private healRatio: number; - /** Should an animation be shown? */ - private showAnim: boolean; - - constructor(healRatio?: number, showAnim?: boolean, selfTarget?: boolean) { - super(selfTarget === undefined || selfTarget); - - this.healRatio = healRatio || 1; - this.showAnim = !!showAnim; + constructor( + /** The percentage of {@linkcode Stat.HP} to heal. */ + private healRatio: number, + /** Whether to display a healing animation when healing the target; default `false` */ + private showAnim = false, + selfTarget = true + ) { + super(selfTarget); } - apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + override apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean { this.addHealPhase(this.selfTarget ? user : target, this.healRatio); return true; } @@ -1981,15 +1985,69 @@ export class HealAttr extends MoveEffectAttr { * Creates a new {@linkcode PokemonHealPhase}. * This heals the target and shows the appropriate message. */ - addHealPhase(target: Pokemon, healRatio: number) { + protected addHealPhase(target: Pokemon, healRatio: number) { globalScene.phaseManager.unshiftNew("PokemonHealPhase", target.getBattlerIndex(), toDmgValue(target.getMaxHp() * healRatio), i18next.t("moveTriggers:healHp", { pokemonName: getPokemonNameWithAffix(target) }), true, !this.showAnim); } - getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { + override getTargetBenefitScore(user: Pokemon, target: Pokemon, _move: Move): number { const score = ((1 - (this.selfTarget ? user : target).getHpRatio()) * 20) - this.healRatio * 10; return Math.round(score / (1 - this.healRatio / 2)); } + + // TODO: Change to fail move + override canApply(user: Pokemon, target: Pokemon, _move: Move, _args?: any[]): boolean { + if (!super.canApply(user, target, _move, _args)) { + return false; + } + + const healedPokemon = this.selfTarget ? user : target; + if (healedPokemon.isFullHp()) { + // Ensure the fail message isn't displayed when checking the move conditions outside of the move execution + // TOOD: Fix this in PR#6276 + if (globalScene.phaseManager.getCurrentPhase()?.is("MovePhase")) { + globalScene.phaseManager.queueMessage(i18next.t("battle:hpIsFull", { + pokemonName: getPokemonNameWithAffix(healedPokemon), + })) + } + return false; + } + return true; + } +} + +/** + * Attribute to put the user to sleep for a fixed duration, fully heal them and cure their status. + * Used for {@linkcode MoveId.REST}. + */ +export class RestAttr extends HealAttr { + private duration: number; + + constructor(duration: number) { + super(1, true); + this.duration = duration; + } + + override apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { + const wasSet = user.trySetStatus(StatusEffect.SLEEP, user, this.duration, null, true, true, + i18next.t("moveTriggers:restBecameHealthy", { + pokemonName: getPokemonNameWithAffix(user), + })); + return wasSet && super.apply(user, target, move, args); + } + + override addHealPhase(user: Pokemon): void { + globalScene.phaseManager.unshiftNew("PokemonHealPhase", user.getBattlerIndex(), user.getMaxHp(), null) + } + + // TODO: change after HealAttr is changed to fail move + override getCondition(): MoveConditionFunc { + return (user, target, move) => + super.canApply(user, target, move, []) + // Intentionally suppress messages here as we display generic fail msg + // TODO: This might have order-of-operation jank + && user.canSetStatus(StatusEffect.SLEEP, true, true, user) + } } /** @@ -2261,20 +2319,9 @@ export class BoostHealAttr extends HealAttr { * @see {@linkcode apply} */ export class HealOnAllyAttr extends HealAttr { - /** - * @param user {@linkcode Pokemon} using the move - * @param target {@linkcode Pokemon} target of the move - * @param move {@linkcode Move} with this attribute - * @param args N/A - * @returns true if the function succeeds - */ - apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - if (user.getAlly() === target) { - super.apply(user, target, move, args); - return true; - } - - return false; + override canApply(user: Pokemon, target: Pokemon, _move: Move, _args?: any[]): boolean { + // Don't trigger if not targeting an ally + return target === user.getAlly() && super.canApply(user, target, _move, _args); } } @@ -2285,6 +2332,7 @@ export class HealOnAllyAttr extends HealAttr { * @see {@linkcode apply} * @see {@linkcode getUserBenefitScore} */ +// TODO: Make Strength Sap its own attribute that extends off of this one export class HitHealAttr extends MoveEffectAttr { private healRatio: number; private healStat: EffectiveStat | null; @@ -2535,49 +2583,50 @@ export class WaterShurikenMultiHitTypeAttr extends ChangeMultiHitTypeAttr { export class StatusEffectAttr extends MoveEffectAttr { public effect: StatusEffect; - public turnsRemaining?: number; - public overrideStatus: boolean = false; - constructor(effect: StatusEffect, selfTarget?: boolean, turnsRemaining?: number, overrideStatus: boolean = false) { + constructor(effect: StatusEffect, selfTarget = false) { super(selfTarget); this.effect = effect; - this.turnsRemaining = turnsRemaining; - this.overrideStatus = overrideStatus; } apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); const statusCheck = moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance; + if (!statusCheck) { + return false; + } + + // non-status moves don't play sound effects for failures const quiet = move.category !== MoveCategory.STATUS; - if (statusCheck) { - const pokemon = this.selfTarget ? user : target; - if (user !== target && move.category === MoveCategory.STATUS && !target.canSetStatus(this.effect, quiet, false, user, true)) { - return false; - } - if (((!pokemon.status || this.overrideStatus) || (pokemon.status.effect === this.effect && moveChance < 0)) - && pokemon.trySetStatus(this.effect, true, user, this.turnsRemaining, null, this.overrideStatus, quiet)) { - applyAbAttrs("ConfusionOnStatusEffectAbAttr", {pokemon: user, opponent: target, move, effect: this.effect}); - return true; - } + + if ( + target.trySetStatus(this.effect, user, undefined, null, false, quiet) + ) { + applyAbAttrs("ConfusionOnStatusEffectAbAttr", {pokemon: user, opponent: target, move, effect: this.effect}); + return true; } return false; } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { const moveChance = this.getMoveChance(user, target, move, this.selfTarget, false); - const score = (moveChance < 0) ? -10 : Math.floor(moveChance * -0.1); + const score = moveChance < 0 ? -10 : Math.floor(moveChance * -0.1); const pokemon = this.selfTarget ? user : target; - return !pokemon.status && pokemon.canSetStatus(this.effect, true, false, user) ? score : 0; + return pokemon.canSetStatus(this.effect, true, false, user) ? score : 0; } } +/** + * Attribute to randomly apply one of several statuses to the target. + * Used for {@linkcode Moves.TRI_ATTACK} and {@linkcode Moves.DIRE_CLAW}. + */ export class MultiStatusEffectAttr extends StatusEffectAttr { public effects: StatusEffect[]; - constructor(effects: StatusEffect[], selfTarget?: boolean, turnsRemaining?: number, overrideStatus?: boolean) { - super(effects[0], selfTarget, turnsRemaining, overrideStatus); + constructor(effects: StatusEffect[], selfTarget?: boolean) { + super(effects[0], selfTarget); this.effects = effects; } @@ -2610,26 +2659,41 @@ export class PsychoShiftEffectAttr extends MoveEffectAttr { * @returns - Whether the effect was successfully applied to the target. */ apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean { - const statusToApply: StatusEffect | undefined = user.status?.effect ?? (user.hasAbility(AbilityId.COMATOSE) ? StatusEffect.SLEEP : undefined); + const statusToApply = user.status?.effect ?? + (user.hasAbility(AbilityId.COMATOSE) ? StatusEffect.SLEEP : StatusEffect.NONE); - if (target.status || !statusToApply) { + // Bang is justified as condition func returns early if no status is found + if (!target.trySetStatus(statusToApply, user)) { return false; - } else { - const canSetStatus = target.canSetStatus(statusToApply, true, false, user); - const trySetStatus = canSetStatus ? target.trySetStatus(statusToApply, true, user) : false; + } - if (trySetStatus && user.status) { - // PsychoShiftTag is added to the user if move succeeds so that the user is healed of its status effect after its move - user.addTag(BattlerTagType.PSYCHO_SHIFT); + if (user.status) { + // Add tag to user to heal its status effect after the move ends (unless we have comatose); + // occurs after move use to ensure correct Synchronize timing + user.addTag(BattlerTagType.PSYCHO_SHIFT) + } + + return true; + } + + getCondition(): MoveConditionFunc { + return (user, target) => { + if (target.status?.effect) { + return false; } - return trySetStatus; + const statusToApply = user.status?.effect ?? (user.hasAbility(AbilityId.COMATOSE) ? StatusEffect.SLEEP : StatusEffect.NONE); + return !!statusToApply && target.canSetStatus(statusToApply, false, false, user); } } getTargetBenefitScore(user: Pokemon, target: Pokemon, move: Move): number { - const statusToApply = user.status?.effect ?? (user.hasAbility(AbilityId.COMATOSE) ? StatusEffect.SLEEP : undefined); - return !target.status && statusToApply && target.canSetStatus(statusToApply, true, false, user) ? -10 : 0; + const statusToApply = + user.status?.effect ?? + (user.hasAbility(AbilityId.COMATOSE) ? StatusEffect.SLEEP : StatusEffect.NONE); + + // TODO: Give this a positive user benefit score + return !target.status?.effect && statusToApply && target.canSetStatus(statusToApply, true, false, user) ? -10 : 0; } } @@ -2689,7 +2753,7 @@ export class StealHeldItemChanceAttr extends MoveEffectAttr { * Used for Incinerate and Knock Off. * Not Implemented Cases: (Same applies for Thief) * "If the user faints due to the target's Ability (Rough Skin or Iron Barbs) or held Rocky Helmet, it cannot remove the target's held item." - * "If the Pokémon is knocked out by the attack, Sticky Hold does not protect the held item."" + * "If the Pokémon is knocked out by the attack, Sticky Hold does not protect the held item." */ export class RemoveHeldItemAttr extends MoveEffectAttr { @@ -2899,7 +2963,7 @@ export class HealStatusEffectAttr extends MoveEffectAttr { */ constructor(selfTarget: boolean, effects: StatusEffect | StatusEffect[]) { super(selfTarget, { lastHitOnly: true }); - this.effects = [ effects ].flat(1); + this.effects = coerceArray(effects) } /** @@ -3938,22 +4002,36 @@ export class BeatUpAttr extends VariablePowerAttr { } } -const doublePowerChanceMessageFunc = (user: Pokemon, target: Pokemon, move: Move) => { - let message: string = ""; - globalScene.executeWithSeedOffset(() => { - const rand = randSeedInt(100); - if (rand < move.chance) { - message = i18next.t("moveTriggers:goingAllOutForAttack", { pokemonName: getPokemonNameWithAffix(user) }); - } - }, globalScene.currentBattle.turn << 6, globalScene.waveSeed); - return message; -}; +/** + * Message function for {@linkcode MoveId.FICKLE_BEAM} that shows a message before move use if + * the move's power would be boosted. + * @todo Find another way to synchronize the RNG calls of Fickle Beam with its message + * than using a seed offset + */ +function doublePowerChanceMessageFunc(chance: number) { + return (user: Pokemon, target: Pokemon, move: Move) => { + let message: string = ""; + globalScene.executeWithSeedOffset(() => { + const rand = randSeedInt(100); + if (rand < chance) { + message = i18next.t("moveTriggers:goingAllOutForAttack", { pokemonName: getPokemonNameWithAffix(user) }); + } + }, globalScene.currentBattle.turn << 6, globalScene.waveSeed); + return message; + }; +} export class DoublePowerChanceAttr extends VariablePowerAttr { + private chance: number; + constructor(chance: number) { + super(false) + this.chance = chance + } + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { - let rand: number; + let rand = 0; globalScene.executeWithSeedOffset(() => rand = randSeedInt(100), globalScene.currentBattle.turn << 6, globalScene.waveSeed); - if (rand! < move.chance) { + if (rand < this.chance) { const power = args[0] as NumberHolder; power.value *= 2; return true; @@ -4426,6 +4504,10 @@ export class SpitUpPowerAttr extends VariablePowerAttr { * Does NOT remove stockpiled stacks. */ export class SwallowHealAttr extends HealAttr { + constructor() { + super(1) + } + apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const stockpilingTag = user.getTag(StockpilingTag); @@ -6065,7 +6147,7 @@ export class AddArenaTrapTagAttr extends AddArenaTagAttr { getCondition(): MoveConditionFunc { return (user, target, move) => { const side = (this.selfSideTarget !== user.isPlayer()) ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER; - const tag = globalScene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; + const tag = globalScene.arena.getTagOnSide(this.tagType, side) as EntryHazardTag; if (!tag) { return true; } @@ -6090,7 +6172,7 @@ export class AddArenaTrapTagHitAttr extends AddArenaTagAttr { apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { const moveChance = this.getMoveChance(user, target, move, this.selfTarget, true); const side = (this.selfSideTarget ? user : target).isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; - const tag = globalScene.arena.getTagOnSide(this.tagType, side) as ArenaTrapTag; + const tag = globalScene.arena.getTagOnSide(this.tagType, side) as EntryHazardTag; if ((moveChance < 0 || moveChance === 100 || user.randBattleSeedInt(100) < moveChance) && user.getLastXMoves(1)[0]?.result === MoveResult.SUCCESS) { globalScene.arena.addTag(this.tagType, 0, move.id, user.id, side); if (!tag) { @@ -6615,7 +6697,7 @@ export class CopyBiomeTypeAttr extends MoveEffectAttr { user.summonData.types = [ typeChange ]; user.updateInfo(); - globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), typeName: i18next.t(`pokemonInfo:Type.${PokemonType[typeChange]}`) })); + globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), typeName: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[typeChange])}`) })); return true; } @@ -6743,7 +6825,7 @@ export class AddTypeAttr extends MoveEffectAttr { target.summonData.addedType = this.type; target.updateInfo(); - globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:addType", { typeName: i18next.t(`pokemonInfo:Type.${PokemonType[this.type]}`), pokemonName: getPokemonNameWithAffix(target) })); + globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:addType", { typeName: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[this.type])}`), pokemonName: getPokemonNameWithAffix(target) })); return true; } @@ -6765,7 +6847,7 @@ export class FirstMoveTypeAttr extends MoveEffectAttr { const firstMoveType = target.getMoveset()[0].getMove().type; user.summonData.types = [ firstMoveType ]; - globalScene.phaseManager.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: i18next.t(`pokemonInfo:Type.${PokemonType[firstMoveType]}`) })); + globalScene.phaseManager.queueMessage(i18next.t("battle:transformedIntoType", { pokemonName: getPokemonNameWithAffix(user), type: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[firstMoveType])}`) })); return true; } @@ -7849,7 +7931,7 @@ export class StatusIfBoostedAttr extends MoveEffectAttr { */ apply(user: Pokemon, target: Pokemon, move: Move, args: any[]): boolean { if (target.turnData.statStagesIncreased) { - target.trySetStatus(this.effect, true, user); + target.trySetStatus(this.effect, user); } return true; } @@ -7996,11 +8078,11 @@ const failIfDampCondition: MoveConditionFunc = (user, target, move) => { return !cancelled.value; }; -const userSleptOrComatoseCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => user.status?.effect === StatusEffect.SLEEP || user.hasAbility(AbilityId.COMATOSE); +const userSleptOrComatoseCondition: MoveConditionFunc = (user) => user.status?.effect === StatusEffect.SLEEP || user.hasAbility(AbilityId.COMATOSE); -const targetSleptOrComatoseCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => target.status?.effect === StatusEffect.SLEEP || target.hasAbility(AbilityId.COMATOSE); +const targetSleptOrComatoseCondition: MoveConditionFunc = (_user: Pokemon, target: Pokemon, _move: Move) => target.status?.effect === StatusEffect.SLEEP || target.hasAbility(AbilityId.COMATOSE); -const failIfLastCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => globalScene.phaseManager.phaseQueue.find(phase => phase.is("MovePhase")) !== undefined; +const failIfLastCondition: MoveConditionFunc = () => globalScene.phaseManager.findPhase(phase => phase.is("MovePhase")) !== undefined; const failIfLastInPartyCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => { const party: Pokemon[] = user.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty(); @@ -8422,8 +8504,6 @@ const MoveAttrs = Object.freeze({ /** Map of of move attribute names to their constructors */ export type MoveAttrConstructorMap = typeof MoveAttrs; -export const selfStatLowerMoves: MoveId[] = []; - export function initMoves() { allMoves.push( new SelfStatusMove(MoveId.NONE, PokemonType.NORMAL, MoveCategory.STATUS, -1, -1, 0, 1), @@ -8877,9 +8957,7 @@ export function initMoves() { .attr(MultiHitAttr, MultiHitType._2) .makesContact(false), new SelfStatusMove(MoveId.REST, PokemonType.PSYCHIC, -1, 5, -1, 0, 1) - .attr(StatusEffectAttr, StatusEffect.SLEEP, true, 3, true) - .attr(HealAttr, 1, true) - .condition((user, target, move) => !user.isFullHp() && user.canSetStatus(StatusEffect.SLEEP, true, true, user)) + .attr(RestAttr, 3) .triageMove(), new AttackMove(MoveId.ROCK_SLIDE, PokemonType.ROCK, MoveCategory.PHYSICAL, 75, 90, 10, 30, 0, 1) .attr(FlinchAttr) @@ -9225,14 +9303,16 @@ export function initMoves() { .condition(user => (user.getTag(StockpilingTag)?.stockpiledCount ?? 0) < 3) .attr(AddBattlerTagAttr, BattlerTagType.STOCKPILING, true), new AttackMove(MoveId.SPIT_UP, PokemonType.NORMAL, MoveCategory.SPECIAL, -1, 100, 10, -1, 0, 3) - .condition(hasStockpileStacksCondition) .attr(SpitUpPowerAttr, 100) + .condition(hasStockpileStacksCondition) .attr(RemoveBattlerTagAttr, [ BattlerTagType.STOCKPILING ], true), new SelfStatusMove(MoveId.SWALLOW, PokemonType.NORMAL, -1, 10, -1, 0, 3) - .condition(hasStockpileStacksCondition) .attr(SwallowHealAttr) + .condition(hasStockpileStacksCondition) .attr(RemoveBattlerTagAttr, [ BattlerTagType.STOCKPILING ], true) - .triageMove(), + .triageMove() + // TODO: Verify if using Swallow at full HP still consumes stacks or not + .edgeCase(), new AttackMove(MoveId.HEAT_WAVE, PokemonType.FIRE, MoveCategory.SPECIAL, 95, 90, 10, 10, 0, 3) .attr(HealStatusEffectAttr, true, StatusEffect.FREEZE) .attr(StatusEffectAttr, StatusEffect.BURN) @@ -9618,14 +9698,8 @@ export function initMoves() { .unimplemented(), new StatusMove(MoveId.PSYCHO_SHIFT, PokemonType.PSYCHIC, 100, 10, -1, 0, 4) .attr(PsychoShiftEffectAttr) - .condition((user, target, move) => { - let statusToApply = user.hasAbility(AbilityId.COMATOSE) ? StatusEffect.SLEEP : undefined; - if (user.status?.effect && isNonVolatileStatusEffect(user.status.effect)) { - statusToApply = user.status.effect; - } - return !!statusToApply && target.canSetStatus(statusToApply, false, false, user); - } - ), + // TODO: Verify status applied if a statused pokemon obtains Comatose (via Transform) and uses Psycho Shift + .edgeCase(), new AttackMove(MoveId.TRUMP_CARD, PokemonType.NORMAL, MoveCategory.SPECIAL, -1, -1, 5, -1, 0, 4) .makesContact() .attr(LessPPMorePowerAttr), @@ -11327,9 +11401,9 @@ export function initMoves() { new AttackMove(MoveId.RUINATION, PokemonType.DARK, MoveCategory.SPECIAL, -1, 90, 10, -1, 0, 9) .attr(TargetHalfHpDamageAttr), new AttackMove(MoveId.COLLISION_COURSE, PokemonType.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 ? 4 / 3 : 1), new AttackMove(MoveId.ELECTRO_DRIFT, PokemonType.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 ? 4 / 3 : 1) .makesContact(), new SelfStatusMove(MoveId.SHED_TAIL, PokemonType.NORMAL, -1, 10, -1, 0, 9) .attr(AddSubstituteAttr, 0.5, true) @@ -11434,10 +11508,9 @@ export function initMoves() { .attr(TeraStarstormTypeAttr) .attr(VariableTargetAttr, (user, target, move) => user.hasSpecies(SpeciesId.TERAPAGOS) && (user.isTerastallized || globalScene.currentBattle.preTurnCommands[user.getFieldIndex()]?.command === Command.TERA) ? MoveTarget.ALL_NEAR_ENEMIES : MoveTarget.NEAR_OTHER) .partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */ - new AttackMove(MoveId.FICKLE_BEAM, PokemonType.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, 30, 0, 9) - .attr(PreMoveMessageAttr, doublePowerChanceMessageFunc) - .attr(DoublePowerChanceAttr) - .edgeCase(), // Should not interact with Sheer Force + new AttackMove(MoveId.FICKLE_BEAM, PokemonType.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, -1, 0, 9) + .attr(PreMoveMessageAttr, doublePowerChanceMessageFunc(30)) + .attr(DoublePowerChanceAttr, 30), new SelfStatusMove(MoveId.BURNING_BULWARK, PokemonType.FIRE, -1, 10, -1, 4, 9) .attr(ProtectAttr, BattlerTagType.BURNING_BULWARK) .condition(failIfLastCondition), @@ -11480,9 +11553,4 @@ export function initMoves() { new AttackMove(MoveId.MALIGNANT_CHAIN, PokemonType.POISON, MoveCategory.SPECIAL, 100, 100, 5, 50, 0, 9) .attr(StatusEffectAttr, StatusEffect.TOXIC) ); - allMoves.map(m => { - if (m.getAttrs("StatStageChangeAttr").some(a => a.selfTarget && a.stages < 0)) { - selfStatLowerMoves.push(m.id); - } - }); } 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 ac3d4def654..66364bfc485 100644 --- a/src/data/mystery-encounters/encounters/a-trainers-test-encounter.ts +++ b/src/data/mystery-encounters/encounters/a-trainers-test-encounter.ts @@ -82,7 +82,7 @@ export const ATrainersTestEncounter: MysteryEncounter = MysteryEncounterBuilder. encounter.dialogue.intro = [ { speaker: `trainerNames:${trainerNameKey}`, - text: `${namespace}:${trainerNameKey}.intro_dialogue`, + text: `${namespace}:${trainerNameKey}.introDialogue`, }, ]; encounter.options[0].dialogue!.selected = [ diff --git a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts index d6058eb9eaf..bf9c49e8c5b 100644 --- a/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts +++ b/src/data/mystery-encounters/encounters/absolute-avarice-encounter.ts @@ -237,7 +237,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = MysteryEncounterBuilde modifierConfigs: bossModifierConfigs, tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { - queueEncounterMessage(`${namespace}:option.1.boss_enraged`); + queueEncounterMessage(`${namespace}:option.1.bossEnraged`); globalScene.phaseManager.unshiftNew( "StatStageChangePhase", pokemon.getBattlerIndex(), @@ -300,7 +300,7 @@ export const AbsoluteAvariceEncounter: MysteryEncounter = MysteryEncounterBuilde globalScene.addModifier(seedModifier, false, false, false, true); } }); - queueEncounterMessage(`${namespace}:option.1.food_stash`); + queueEncounterMessage(`${namespace}:option.1.foodStash`); }; setEncounterRewards({ fillRemaining: true }, undefined, givePartyPokemonReviverSeeds); 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 619acabe200..7d4fb0ef98f 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 @@ -71,7 +71,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = MysteryEncounterB text: `${namespace}:intro`, }, { - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, speaker: `${namespace}:speaker`, }, ]) @@ -152,7 +152,7 @@ export const AnOfferYouCantRefuseEncounter: MysteryEncounter = MysteryEncounterB .withDialogue({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.tooltip_disabled`, + disabledButtonTooltip: `${namespace}:option.2.tooltipDisabled`, selected: [ { speaker: `${namespace}:speaker`, diff --git a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts index a827c3fcc0a..196ca873f4e 100644 --- a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts +++ b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts @@ -254,7 +254,7 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder. undefined, doBerryRewards, ); - await showEncounterText(`${namespace}:option.2.selected_bad`); + await showEncounterText(`${namespace}:option.2.selectedBad`); await initBattleWithEnemyConfig(config); return; } 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 c5553e9bb95..6750051c3c4 100644 --- a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts +++ b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts @@ -198,7 +198,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]) .withOnInit(() => { @@ -312,7 +312,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde .withDialogue({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.2.disabledTooltip`, }) .withPreOptionPhase(async () => { // Player shows off their bug types @@ -333,7 +333,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde encounter.selectedOption!.dialogue!.selected = [ { speaker: `${namespace}:speaker`, - text: `${namespace}:option.2.selected_0_to_1`, + text: `${namespace}:option.2.selected0To1`, }, ]; } else if (numBugTypes < 4) { @@ -344,7 +344,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde encounter.selectedOption!.dialogue!.selected = [ { speaker: `${namespace}:speaker`, - text: `${namespace}:option.2.selected_2_to_3`, + text: `${namespace}:option.2.selected2To3`, }, ]; } else if (numBugTypes < 6) { @@ -355,7 +355,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde encounter.selectedOption!.dialogue!.selected = [ { speaker: `${namespace}:speaker`, - text: `${namespace}:option.2.selected_4_to_5`, + text: `${namespace}:option.2.selected4To5`, }, ]; } else { @@ -398,7 +398,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde encounter.selectedOption!.dialogue!.selected = [ { speaker: `${namespace}:speaker`, - text: `${namespace}:option.2.selected_6`, + text: `${namespace}:option.2.selected6`, }, ]; } @@ -421,17 +421,17 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, selected: [ { text: `${namespace}:option.3.selected`, }, { speaker: `${namespace}:speaker`, - text: `${namespace}:option.3.selected_dialogue`, + text: `${namespace}:option.3.selectedDialogue`, }, ], - secondOptionPrompt: `${namespace}:option.3.select_prompt`, + secondOptionPrompt: `${namespace}:option.3.selectPrompt`, }) .withPreOptionPhase(async (): Promise => { const encounter = globalScene.currentBattle.mysteryEncounter!; @@ -476,7 +476,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde ); }); if (!hasValidItem) { - return getEncounterText(`${namespace}:option.3.invalid_selection`) ?? null; + return getEncounterText(`${namespace}:option.3.invalidSelection`) ?? null; } return null; @@ -514,7 +514,7 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde function getTrainerConfigForWave(waveIndex: number) { // Bug type superfan trainer config const config = trainerConfigs[TrainerType.BUG_TYPE_SUPERFAN].clone(); - config.name = i18next.t("trainerNames:bug_type_superfan"); + config.name = i18next.t("trainerNames:bugTypeSuperfan"); let pool3Copy = POOL_3_POKEMON.slice(0); pool3Copy = randSeedShuffle(pool3Copy); @@ -713,7 +713,7 @@ function doBugTypeMoveTutor(): Promise { // biome-ignore lint/suspicious/noAsyncPromiseExecutor: TODO explain return new Promise(async resolve => { const moveOptions = globalScene.currentBattle.mysteryEncounter!.misc.moveTutorOptions; - await showEncounterDialogue(`${namespace}:battle_won`, `${namespace}:speaker`); + await showEncounterDialogue(`${namespace}:battleWon`, `${namespace}:speaker`); const moveInfoOverlay = new MoveInfoOverlay({ delayVisibility: false, @@ -748,7 +748,7 @@ function doBugTypeMoveTutor(): Promise { const result = await selectOptionThenPokemon( optionSelectItems, - `${namespace}:teach_move_prompt`, + `${namespace}:teachMovePrompt`, undefined, onHoverOverCancel, ); diff --git a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts index 092cc4931af..09e59c7e391 100644 --- a/src/data/mystery-encounters/encounters/clowning-around-encounter.ts +++ b/src/data/mystery-encounters/encounters/clowning-around-encounter.ts @@ -119,7 +119,7 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder text: `${namespace}:intro`, }, { - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, speaker: `${namespace}:speaker`, }, ]) @@ -233,7 +233,7 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder // After the battle, offer the player the opportunity to permanently swap ability const abilityWasSwapped = await handleSwapAbility(); if (abilityWasSwapped) { - await showEncounterText(`${namespace}:option.1.ability_gained`); + await showEncounterText(`${namespace}:option.1.abilityGained`); } // Play animations once ability swap is complete @@ -267,10 +267,10 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder speaker: `${namespace}:speaker`, }, { - text: `${namespace}:option.2.selected_2`, + text: `${namespace}:option.2.selected2`, }, { - text: `${namespace}:option.2.selected_3`, + text: `${namespace}:option.2.selected3`, speaker: `${namespace}:speaker`, }, ], @@ -359,10 +359,10 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder speaker: `${namespace}:speaker`, }, { - text: `${namespace}:option.3.selected_2`, + text: `${namespace}:option.3.selected2`, }, { - text: `${namespace}:option.3.selected_3`, + text: `${namespace}:option.3.selected3`, speaker: `${namespace}:speaker`, }, ], @@ -432,8 +432,8 @@ export const ClowningAroundEncounter: MysteryEncounter = MysteryEncounterBuilder async function handleSwapAbility() { // biome-ignore lint/suspicious/noAsyncPromiseExecutor: TODO: Consider refactoring to avoid async promise executor return new Promise(async resolve => { - await showEncounterDialogue(`${namespace}:option.1.apply_ability_dialogue`, `${namespace}:speaker`); - await showEncounterText(`${namespace}:option.1.apply_ability_message`); + await showEncounterDialogue(`${namespace}:option.1.applyAbilityDialogue`, `${namespace}:speaker`); + await showEncounterText(`${namespace}:option.1.applyAbilityMessage`); globalScene.ui.setMode(UiMode.MESSAGE).then(() => { displayYesNoOptions(resolve); @@ -442,7 +442,7 @@ async function handleSwapAbility() { } function displayYesNoOptions(resolve) { - showEncounterText(`${namespace}:option.1.ability_prompt`, null, 500, false); + showEncounterText(`${namespace}:option.1.abilityPrompt`, null, 500, false); const fullOptions = [ { label: i18next.t("menu:yes"), diff --git a/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts b/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts index 8dae0eaee3a..e2c330a1106 100644 --- a/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts +++ b/src/data/mystery-encounters/encounters/dancing-lessons-encounter.ts @@ -174,7 +174,7 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder // Gets +1 to all stats except SPD on battle start tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { - queueEncounterMessage(`${namespace}:option.1.boss_enraged`); + queueEncounterMessage(`${namespace}:option.1.bossEnraged`); globalScene.phaseManager.unshiftNew( "StatStageChangePhase", pokemon.getBattlerIndex(), @@ -273,8 +273,8 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, - secondOptionPrompt: `${namespace}:option.3.select_prompt`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, + secondOptionPrompt: `${namespace}:option.3.selectPrompt`, selected: [ { text: `${namespace}:option.3.selected`, @@ -316,7 +316,7 @@ export const DancingLessonsEncounter: MysteryEncounter = MysteryEncounterBuilder } const meetsReqs = encounter.options[2].pokemonMeetsPrimaryRequirements(pokemon); if (!meetsReqs) { - return getEncounterText(`${namespace}:invalid_selection`) ?? null; + return getEncounterText(`${namespace}:invalidSelection`) ?? null; } return null; diff --git a/src/data/mystery-encounters/encounters/dark-deal-encounter.ts b/src/data/mystery-encounters/encounters/dark-deal-encounter.ts index 820c7823320..65d22bfc6de 100644 --- a/src/data/mystery-encounters/encounters/dark-deal-encounter.ts +++ b/src/data/mystery-encounters/encounters/dark-deal-encounter.ts @@ -119,7 +119,7 @@ export const DarkDealEncounter: MysteryEncounter = MysteryEncounterBuilder.withE }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]) .withSceneWaveRangeRequirement(30, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1]) @@ -137,10 +137,10 @@ export const DarkDealEncounter: MysteryEncounter = MysteryEncounterBuilder.withE selected: [ { speaker: `${namespace}:speaker`, - text: `${namespace}:option.1.selected_dialogue`, + text: `${namespace}:option.1.selectedDialogue`, }, { - text: `${namespace}:option.1.selected_message`, + text: `${namespace}:option.1.selectedMessage`, }, ], }) diff --git a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts index 85102a01ce1..8cd4c8bee66 100644 --- a/src/data/mystery-encounters/encounters/delibirdy-encounter.ts +++ b/src/data/mystery-encounters/encounters/delibirdy-encounter.ts @@ -193,7 +193,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with .withDialogue({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - secondOptionPrompt: `${namespace}:option.2.select_prompt`, + secondOptionPrompt: `${namespace}:option.2.selectPrompt`, selected: [ { text: `${namespace}:option.2.selected`, @@ -229,7 +229,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with // If pokemon has valid item, it can be selected const meetsReqs = encounter.options[1].pokemonMeetsPrimaryRequirements(pokemon); if (!meetsReqs) { - return getEncounterText(`${namespace}:invalid_selection`) ?? null; + return getEncounterText(`${namespace}:invalidSelection`) ?? null; } return null; @@ -303,7 +303,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - secondOptionPrompt: `${namespace}:option.3.select_prompt`, + secondOptionPrompt: `${namespace}:option.3.selectPrompt`, selected: [ { text: `${namespace}:option.3.selected`, @@ -341,7 +341,7 @@ export const DelibirdyEncounter: MysteryEncounter = MysteryEncounterBuilder.with // If pokemon has valid item, it can be selected const meetsReqs = encounter.options[2].pokemonMeetsPrimaryRequirements(pokemon); if (!meetsReqs) { - return getEncounterText(`${namespace}:invalid_selection`) ?? null; + return getEncounterText(`${namespace}:invalidSelection`) ?? null; } return null; 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 a45c5301a3e..754e8c883e8 100644 --- a/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts +++ b/src/data/mystery-encounters/encounters/department-store-sale-encounter.ts @@ -43,7 +43,7 @@ export const DepartmentStoreSaleEncounter: MysteryEncounter = MysteryEncounterBu text: `${namespace}:intro`, }, { - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, speaker: `${namespace}:speaker`, }, ]) diff --git a/src/data/mystery-encounters/encounters/field-trip-encounter.ts b/src/data/mystery-encounters/encounters/field-trip-encounter.ts index 0413c3d0e1d..67a7cad3466 100644 --- a/src/data/mystery-encounters/encounters/field-trip-encounter.ts +++ b/src/data/mystery-encounters/encounters/field-trip-encounter.ts @@ -56,7 +56,7 @@ export const FieldTripEncounter: MysteryEncounter = MysteryEncounterBuilder.with text: `${namespace}:intro`, }, { - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, speaker: `${namespace}:speaker`, }, ]) @@ -70,7 +70,7 @@ export const FieldTripEncounter: MysteryEncounter = MysteryEncounterBuilder.with .withDialogue({ buttonLabel: `${namespace}:option.1.label`, buttonTooltip: `${namespace}:option.1.tooltip`, - secondOptionPrompt: `${namespace}:second_option_prompt`, + secondOptionPrompt: `${namespace}:secondOptionPrompt`, }) .withPreOptionPhase(async (): Promise => { const encounter = globalScene.currentBattle.mysteryEncounter!; @@ -118,7 +118,7 @@ export const FieldTripEncounter: MysteryEncounter = MysteryEncounterBuilder.with .withDialogue({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - secondOptionPrompt: `${namespace}:second_option_prompt`, + secondOptionPrompt: `${namespace}:secondOptionPrompt`, }) .withPreOptionPhase(async (): Promise => { const encounter = globalScene.currentBattle.mysteryEncounter!; @@ -166,7 +166,7 @@ export const FieldTripEncounter: MysteryEncounter = MysteryEncounterBuilder.with .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - secondOptionPrompt: `${namespace}:second_option_prompt`, + secondOptionPrompt: `${namespace}:secondOptionPrompt`, }) .withPreOptionPhase(async (): Promise => { const encounter = globalScene.currentBattle.mysteryEncounter!; @@ -226,7 +226,7 @@ function pokemonAndMoveChosen(pokemon: PlayerPokemon, move: PokemonMove, correct speaker: `${namespace}:speaker`, }, { - text: `${namespace}:incorrect_exp`, + text: `${namespace}:incorrectExp`, }, ]; setEncounterExp( @@ -243,7 +243,7 @@ function pokemonAndMoveChosen(pokemon: PlayerPokemon, move: PokemonMove, correct speaker: `${namespace}:speaker`, }, { - text: `${namespace}:correct_exp`, + text: `${namespace}:correctExp`, }, ]; setEncounterExp([pokemon.id], 100); diff --git a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts index 7d2583a00cb..1cc31eaa21f 100644 --- a/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts +++ b/src/data/mystery-encounters/encounters/fiery-fallout-encounter.ts @@ -243,11 +243,12 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w if (burnable?.length > 0) { const roll = randSeedInt(burnable.length); const chosenPokemon = burnable[roll]; - if (chosenPokemon.trySetStatus(StatusEffect.BURN)) { + if (chosenPokemon.canSetStatus(StatusEffect.BURN, true)) { // Burn applied + chosenPokemon.doSetStatus(StatusEffect.BURN); encounter.setDialogueToken("burnedPokemon", chosenPokemon.getNameToRender()); encounter.setDialogueToken("abilityName", allAbilities[AbilityId.HEATPROOF].name); - queueEncounterMessage(`${namespace}:option.2.target_burned`); + queueEncounterMessage(`${namespace}:option.2.targetBurned`); // Also permanently change the burned Pokemon's ability to Heatproof applyAbilityOverrideToPokemon(chosenPokemon, AbilityId.HEATPROOF); @@ -269,7 +270,7 @@ export const FieryFalloutEncounter: MysteryEncounter = MysteryEncounterBuilder.w .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, selected: [ { text: `${namespace}:option.3.selected`, @@ -313,6 +314,6 @@ function giveLeadPokemonAttackTypeBoostItem() { const encounter = globalScene.currentBattle.mysteryEncounter!; encounter.setDialogueToken("itemName", boosterModifierType.name); encounter.setDialogueToken("leadPokemon", leadPokemon.getNameToRender()); - queueEncounterMessage(`${namespace}:found_item`); + queueEncounterMessage(`${namespace}:foundItem`); } } 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 6ee2ebcdf67..f7dc89b44fd 100644 --- a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts +++ b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts @@ -69,7 +69,7 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder. isBoss: true, tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { - queueEncounterMessage(`${namespace}:option.1.stat_boost`); + queueEncounterMessage(`${namespace}:option.1.statBoost`); // Randomly boost 1 stat 2 stages // Cannot boost Spd, Acc, or Evasion globalScene.phaseManager.unshiftNew( @@ -165,7 +165,7 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder. .withDialogue({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.2.disabledTooltip`, selected: [ { text: `${namespace}:option.2.selected`, 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 bf376c04843..d883fdbb567 100644 --- a/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts +++ b/src/data/mystery-encounters/encounters/fun-and-games-encounter.ts @@ -78,7 +78,7 @@ export const FunAndGamesEncounter: MysteryEncounter = MysteryEncounterBuilder.wi .withIntroDialogue([ { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]) .setLocalizationKey(`${namespace}`) @@ -118,7 +118,7 @@ export const FunAndGamesEncounter: MysteryEncounter = MysteryEncounterBuilder.wi // Only Pokemon that are not KOed/legal can be selected const selectableFilter = (pokemon: Pokemon) => { - return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalid_selection`); + return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalidSelection`); }; return selectPokemonForOption(onPokemonSelected, undefined, selectableFilter); @@ -132,7 +132,7 @@ export const FunAndGamesEncounter: MysteryEncounter = MysteryEncounterBuilder.wi const moneyCost = (encounter.options[0].requirements[0] as MoneyRequirement).requiredMoney; updatePlayerMoney(-moneyCost, true, false); await showEncounterText( - i18next.t("mysteryEncounterMessages:paid_money", { + i18next.t("mysteryEncounterMessages:paidMoney", { amount: moneyCost, }), ); @@ -284,25 +284,25 @@ function handleNextTurn() { guaranteedModifierTypeFuncs: [modifierTypes.MULTI_LENS], fillRemaining: false, }); - resultMessageKey = `${namespace}:best_result`; + resultMessageKey = `${namespace}:bestResult`; } else if (healthRatio < 0.15) { // 2nd prize setEncounterRewards({ guaranteedModifierTypeFuncs: [modifierTypes.SCOPE_LENS], fillRemaining: false, }); - resultMessageKey = `${namespace}:great_result`; + resultMessageKey = `${namespace}:greatResult`; } else if (healthRatio < 0.33) { // 3rd prize setEncounterRewards({ guaranteedModifierTypeFuncs: [modifierTypes.WIDE_LENS], fillRemaining: false, }); - resultMessageKey = `${namespace}:good_result`; + resultMessageKey = `${namespace}:goodResult`; } else { // No prize isHealPhase = true; - resultMessageKey = `${namespace}:bad_result`; + resultMessageKey = `${namespace}:badResult`; } // End the battle @@ -312,7 +312,7 @@ function handleNextTurn() { globalScene.currentBattle.mysteryEncounter!.doContinueEncounter = undefined; leaveEncounterWithoutBattle(isHealPhase); // Must end the TurnInit phase prematurely so battle phases aren't added to queue - queueEncounterMessage(`${namespace}:end_game`); + queueEncounterMessage(`${namespace}:endGame`); queueEncounterMessage(resultMessageKey); // Skip remainder of TurnInitPhase @@ -320,9 +320,9 @@ function handleNextTurn() { } if (encounter.misc.turnsRemaining < 3) { // Display charging messages on turns that aren't the initial turn - queueEncounterMessage(`${namespace}:charging_continue`); + queueEncounterMessage(`${namespace}:chargingContinue`); } - queueEncounterMessage(`${namespace}:turn_remaining_${encounter.misc.turnsRemaining}`); + queueEncounterMessage(`${namespace}:turnRemaining${encounter.misc.turnsRemaining}`); encounter.misc.turnsRemaining--; // Don't skip remainder of TurnInitPhase 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 ed49fccf190..a8dafdaa848 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -44,7 +44,10 @@ import { PokemonData } from "#system/pokemon-data"; import { MusicPreference } from "#system/settings"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler"; import { isNullOrUndefined, NumberHolder, randInt, randSeedInt, randSeedItem, randSeedShuffle } from "#utils/common"; +import { getEnumKeys } from "#utils/enums"; +import { getRandomLocaleEntry } from "#utils/i18n"; import { getPokemonSpecies } from "#utils/pokemon-utils"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; /** the i18n namespace for the encounter */ @@ -158,7 +161,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil .withDialogue({ buttonLabel: `${namespace}:option.1.label`, buttonTooltip: `${namespace}:option.1.tooltip`, - secondOptionPrompt: `${namespace}:option.1.trade_options_prompt`, + secondOptionPrompt: `${namespace}:option.1.tradeOptionsPrompt`, }) .withPreOptionPhase(async (): Promise => { const encounter = globalScene.currentBattle.mysteryEncounter!; @@ -248,7 +251,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil // Show the trade animation await showTradeBackground(); await doPokemonTradeSequence(tradedPokemon, newPlayerPokemon); - await showEncounterText(`${namespace}:trade_received`, null, 0, true, 4000); + await showEncounterText(`${namespace}:tradeReceived`, null, 0, true, 4000); globalScene.playBgm(encounter.misc.bgmKey); await addPokemonDataToDexAndValidateAchievements(newPlayerPokemon); await hideTradeBackground(); @@ -369,7 +372,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil // Show the trade animation await showTradeBackground(); await doPokemonTradeSequence(tradedPokemon, newPlayerPokemon); - await showEncounterText(`${namespace}:trade_received`, null, 0, true, 4000); + await showEncounterText(`${namespace}:tradeReceived`, null, 0, true, 4000); globalScene.playBgm(encounter.misc.bgmKey); await addPokemonDataToDexAndValidateAchievements(newPlayerPokemon); await hideTradeBackground(); @@ -384,7 +387,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - secondOptionPrompt: `${namespace}:option.3.trade_options_prompt`, + secondOptionPrompt: `${namespace}:option.3.tradeOptionsPrompt`, }) .withPreOptionPhase(async (): Promise => { const encounter = globalScene.currentBattle.mysteryEncounter!; @@ -416,7 +419,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil return it.isTransferable; }).length > 0; if (!meetsReqs) { - return getEncounterText(`${namespace}:option.3.invalid_selection`) ?? null; + return getEncounterText(`${namespace}:option.3.invalidSelection`) ?? null; } return null; @@ -468,7 +471,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil // Generate a trainer name const traderName = generateRandomTraderName(); encounter.setDialogueToken("tradeTrainerName", traderName.trim()); - await showEncounterText(`${namespace}:item_trade_selected`); + await showEncounterText(`${namespace}:itemTradeSelected`); leaveEncounterWithoutBattle(); }) .build(), @@ -740,10 +743,10 @@ function doPokemonTradeSequence(tradedPokemon: PlayerPokemon, receivedPokemon: P duration: 500, onComplete: async () => { globalScene.fadeOutBgm(1000, false); - await showEncounterText(`${namespace}:pokemon_trade_selected`); + await showEncounterText(`${namespace}:pokemonTradeSelected`); tradedPokemon.cry(); globalScene.playBgm("evolution"); - await showEncounterText(`${namespace}:pokemon_trade_goodbye`); + await showEncounterText(`${namespace}:pokemonTradeGoodbye`); tradedPokeball.setAlpha(0); tradedPokeball.setVisible(true); @@ -984,14 +987,17 @@ function doTradeReceivedSequence( } function generateRandomTraderName() { - const length = TrainerType.YOUNGSTER - TrainerType.ACE_TRAINER + 1; - // +1 avoids TrainerType.UNKNOWN - const classKey = `trainersCommon:${TrainerType[randInt(length) + 1]}`; - // Some trainers have 2 gendered pools, some do not - const genderKey = i18next.exists(`${classKey}.MALE`) ? (randInt(2) === 0 ? ".MALE" : ".FEMALE") : ""; - const trainerNameKey = randSeedItem(Object.keys(i18next.t(`${classKey}${genderKey}`, { returnObjects: true }))); - const trainerNameString = i18next.t(`${classKey}${genderKey}.${trainerNameKey}`); - // Some names have an '&' symbol and need to be trimmed to a single name instead of a double name - const trainerNames = trainerNameString.split(" & "); - return trainerNames[randInt(trainerNames.length)]; + const allTrainerNames = getEnumKeys(TrainerType); + // Exclude TrainerType.UNKNOWN and everything after Ace Trainers (grunts and unique trainers) + const eligibleNames = allTrainerNames.slice( + 1, + allTrainerNames.indexOf(TrainerType[TrainerType.YOUNGSTER] as keyof typeof TrainerType), + ); + const randomTrainer = toCamelCase(randSeedItem(eligibleNames)); + const classKey = `trainersCommon:${randomTrainer}`; + // Pick a random gender for ones with gendered pools, or access the raw object for ones without. + const genderKey = i18next.exists(`${classKey}.male`) ? randSeedItem([".male", ".female"]) : ""; + const trainerNameString = getRandomLocaleEntry(`${classKey}${genderKey}`)[1]; + // Split the string by &s (for duo trainers) + return randSeedItem(trainerNameString.split(" & ")); } 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 10f45c21b68..f1c79208911 100644 --- a/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts +++ b/src/data/mystery-encounters/encounters/lost-at-sea-encounter.ts @@ -63,9 +63,9 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with .withPokemonCanLearnMoveRequirement(OPTION_1_REQUIRED_MOVE) .withDialogue({ buttonLabel: `${namespace}:option.1.label`, - disabledButtonLabel: `${namespace}:option.1.label_disabled`, + disabledButtonLabel: `${namespace}:option.1.labelDisabled`, buttonTooltip: `${namespace}:option.1.tooltip`, - disabledButtonTooltip: `${namespace}:option.1.tooltip_disabled`, + disabledButtonTooltip: `${namespace}:option.1.tooltipDisabled`, selected: [ { text: `${namespace}:option.1.selected`, @@ -81,9 +81,9 @@ export const LostAtSeaEncounter: MysteryEncounter = MysteryEncounterBuilder.with .withPokemonCanLearnMoveRequirement(OPTION_2_REQUIRED_MOVE) .withDialogue({ buttonLabel: `${namespace}:option.2.label`, - disabledButtonLabel: `${namespace}:option.2.label_disabled`, + disabledButtonLabel: `${namespace}:option.2.labelDisabled`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.tooltip_disabled`, + disabledButtonTooltip: `${namespace}:option.2.tooltipDisabled`, selected: [ { text: `${namespace}:option.2.selected`, diff --git a/src/data/mystery-encounters/encounters/part-timer-encounter.ts b/src/data/mystery-encounters/encounters/part-timer-encounter.ts index a865de3b19d..bf1b077647a 100644 --- a/src/data/mystery-encounters/encounters/part-timer-encounter.ts +++ b/src/data/mystery-encounters/encounters/part-timer-encounter.ts @@ -58,7 +58,7 @@ export const PartTimerEncounter: MysteryEncounter = MysteryEncounterBuilder.with }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]) .withOnInit(() => { @@ -128,7 +128,7 @@ export const PartTimerEncounter: MysteryEncounter = MysteryEncounterBuilder.with // Only Pokemon non-KOd pokemon can be selected const selectableFilter = (pokemon: Pokemon) => { - return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalid_selection`); + return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalidSelection`); }; return selectPokemonForOption(onPokemonSelected, undefined, selectableFilter); @@ -142,18 +142,18 @@ export const PartTimerEncounter: MysteryEncounter = MysteryEncounterBuilder.with // Give money and do dialogue if (moneyMultiplier > 2.5) { - await showEncounterDialogue(`${namespace}:job_complete_good`, `${namespace}:speaker`); + await showEncounterDialogue(`${namespace}:jobCompleteGood`, `${namespace}:speaker`); } else { - await showEncounterDialogue(`${namespace}:job_complete_bad`, `${namespace}:speaker`); + await showEncounterDialogue(`${namespace}:jobCompleteBad`, `${namespace}:speaker`); } const moneyChange = globalScene.getWaveMoneyAmount(moneyMultiplier); updatePlayerMoney(moneyChange, true, false); await showEncounterText( - i18next.t("mysteryEncounterMessages:receive_money", { + i18next.t("mysteryEncounterMessages:receiveMoney", { amount: moneyChange, }), ); - await showEncounterText(`${namespace}:pokemon_tired`); + await showEncounterText(`${namespace}:pokemonTired`); setEncounterRewards({ fillRemaining: true }); leaveEncounterWithoutBattle(); @@ -210,7 +210,7 @@ export const PartTimerEncounter: MysteryEncounter = MysteryEncounterBuilder.with // Only Pokemon non-KOd pokemon can be selected const selectableFilter = (pokemon: Pokemon) => { - return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalid_selection`); + return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalidSelection`); }; return selectPokemonForOption(onPokemonSelected, undefined, selectableFilter); @@ -224,18 +224,18 @@ export const PartTimerEncounter: MysteryEncounter = MysteryEncounterBuilder.with // Give money and do dialogue if (moneyMultiplier > 2.5) { - await showEncounterDialogue(`${namespace}:job_complete_good`, `${namespace}:speaker`); + await showEncounterDialogue(`${namespace}:jobCompleteGood`, `${namespace}:speaker`); } else { - await showEncounterDialogue(`${namespace}:job_complete_bad`, `${namespace}:speaker`); + await showEncounterDialogue(`${namespace}:jobCompleteBad`, `${namespace}:speaker`); } const moneyChange = globalScene.getWaveMoneyAmount(moneyMultiplier); updatePlayerMoney(moneyChange, true, false); await showEncounterText( - i18next.t("mysteryEncounterMessages:receive_money", { + i18next.t("mysteryEncounterMessages:receiveMoney", { amount: moneyChange, }), ); - await showEncounterText(`${namespace}:pokemon_tired`); + await showEncounterText(`${namespace}:pokemonTired`); setEncounterRewards({ fillRemaining: true }); leaveEncounterWithoutBattle(); @@ -248,7 +248,7 @@ export const PartTimerEncounter: MysteryEncounter = MysteryEncounterBuilder.with .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, selected: [ { text: `${namespace}:option.3.selected`, @@ -282,15 +282,15 @@ export const PartTimerEncounter: MysteryEncounter = MysteryEncounterBuilder.with await transitionMysteryEncounterIntroVisuals(false, false); // Give money and do dialogue - await showEncounterDialogue(`${namespace}:job_complete_good`, `${namespace}:speaker`); + await showEncounterDialogue(`${namespace}:jobCompleteGood`, `${namespace}:speaker`); const moneyChange = globalScene.getWaveMoneyAmount(2.5); updatePlayerMoney(moneyChange, true, false); await showEncounterText( - i18next.t("mysteryEncounterMessages:receive_money", { + i18next.t("mysteryEncounterMessages:receiveMoney", { amount: moneyChange, }), ); - await showEncounterText(`${namespace}:pokemon_tired`); + await showEncounterText(`${namespace}:pokemonTired`); setEncounterRewards({ fillRemaining: true }); leaveEncounterWithoutBattle(); diff --git a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts index c3400b41327..764951877f0 100644 --- a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts +++ b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts @@ -205,7 +205,7 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [ // 80% chance to increase flee stage +1 const fleeChangeResult = tryChangeFleeStage(1, 8); if (!fleeChangeResult) { - await showEncounterText(getEncounterText(`${namespace}:safari.busy_eating`) ?? "", null, 1000, false); + await showEncounterText(getEncounterText(`${namespace}:safari.busyEating`) ?? "", null, 1000, false); } else { await showEncounterText(getEncounterText(`${namespace}:safari.eating`) ?? "", null, 1000, false); } @@ -233,7 +233,7 @@ const safariZoneGameOptions: MysteryEncounterOption[] = [ // 80% chance to decrease catch stage -1 const catchChangeResult = tryChangeCatchStage(-1, 8); if (!catchChangeResult) { - await showEncounterText(getEncounterText(`${namespace}:safari.beside_itself_angry`) ?? "", null, 1000, false); + await showEncounterText(getEncounterText(`${namespace}:safari.besideItselfAngry`) ?? "", null, 1000, false); } else { await showEncounterText(getEncounterText(`${namespace}:safari.angry`) ?? "", null, 1000, false); } @@ -274,7 +274,7 @@ async function summonSafariPokemon() { const encounter = globalScene.currentBattle.mysteryEncounter!; // Message pokemon remaining encounter.setDialogueToken("remainingCount", encounter.misc.safariPokemonRemaining); - globalScene.phaseManager.queueMessage(getEncounterText(`${namespace}:safari.remaining_count`) ?? "", null, true); + globalScene.phaseManager.queueMessage(getEncounterText(`${namespace}:safari.remainingCount`) ?? "", null, true); // Generate pokemon using safariPokemonRemaining so they are always the same pokemon no matter how many turns are taken // Safari pokemon roll twice on shiny and HA chances, but are otherwise normal 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 47317c12b50..bf232c616d5 100644 --- a/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts +++ b/src/data/mystery-encounters/encounters/shady-vitamin-dealer-encounter.ts @@ -70,7 +70,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui text: `${namespace}:intro`, }, { - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, speaker: `${namespace}:speaker`, }, ]) @@ -119,7 +119,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui ); } if (!encounter.pokemonMeetsPrimaryRequirements(pokemon)) { - return getEncounterText(`${namespace}:invalid_selection`) ?? null; + return getEncounterText(`${namespace}:invalidSelection`) ?? null; } return null; @@ -155,7 +155,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui chosenPokemon.setCustomNature(newNature); encounter.setDialogueToken("newNature", getNatureName(newNature)); - queueEncounterMessage(`${namespace}:cheap_side_effects`); + queueEncounterMessage(`${namespace}:cheapSideEffects`); setEncounterExp([chosenPokemon.id], 100); await chosenPokemon.updateInfo(); }) @@ -193,7 +193,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui // Only Pokemon that can gain benefits are unfainted const selectableFilter = (pokemon: Pokemon) => { - return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalid_selection`); + return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalidSelection`); }; return selectPokemonForOption(onPokemonSelected, undefined, selectableFilter); @@ -215,7 +215,7 @@ export const ShadyVitaminDealerEncounter: MysteryEncounter = MysteryEncounterBui const encounter = globalScene.currentBattle.mysteryEncounter!; const chosenPokemon = encounter.misc.chosenPokemon; - queueEncounterMessage(`${namespace}:no_bad_effects`); + queueEncounterMessage(`${namespace}:noBadEffects`); setEncounterExp([chosenPokemon.id], 100); await chosenPokemon.updateInfo(); diff --git a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts index cddfef1ef76..8c367882445 100644 --- a/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts +++ b/src/data/mystery-encounters/encounters/slumbering-snorlax-encounter.ts @@ -157,7 +157,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil // Fall asleep waiting for Snorlax // Full heal party globalScene.phaseManager.unshiftNew("PartyHealPhase", true); - queueEncounterMessage(`${namespace}:option.2.rest_result`); + queueEncounterMessage(`${namespace}:option.2.restResult`); leaveEncounterWithoutBattle(); }, ) @@ -167,7 +167,7 @@ export const SlumberingSnorlaxEncounter: MysteryEncounter = MysteryEncounterBuil .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, selected: [ { text: `${namespace}:option.3.selected`, diff --git a/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts b/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts index d77326837cd..58ab3f2ec2d 100644 --- a/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts +++ b/src/data/mystery-encounters/encounters/teleporting-hijinks-encounter.ts @@ -122,7 +122,7 @@ export const TeleportingHijinksEncounter: MysteryEncounter = MysteryEncounterBui .withDialogue({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.2.disabledTooltip`, selected: [ { text: `${namespace}:option.2.selected`, @@ -227,7 +227,7 @@ async function doBiomeTransitionDialogueAndBattleInit() { isBoss: true, tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { - queueEncounterMessage(`${namespace}:boss_enraged`); + queueEncounterMessage(`${namespace}:bossEnraged`); globalScene.phaseManager.unshiftNew( "StatStageChangePhase", pokemon.getBattlerIndex(), 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 7c528e2305b..b5084743613 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 @@ -4,6 +4,7 @@ import { modifierTypes } from "#data/data-lists"; import type { IEggOptions } from "#data/egg"; import { getPokeballTintColor } from "#data/pokeball"; import { BiomeId } from "#enums/biome-id"; +import { Challenges } from "#enums/challenges"; import { EggSourceType } from "#enums/egg-source-types"; import { EggTier } from "#enums/egg-type"; import { MoveId } from "#enums/move-id"; @@ -33,7 +34,7 @@ import i18next from "i18next"; /** the i18n namespace for the encounter */ const namespace = "mysteryEncounters/theExpertPokemonBreeder"; -const trainerNameKey = "trainerNames:expert_pokemon_breeder"; +const trainerNameKey = "trainerNames:expertPokemonBreeder"; const FIRST_STAGE_EVOLUTION_WAVE = 45; const SECOND_STAGE_EVOLUTION_WAVE = 60; @@ -130,6 +131,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount MysteryEncounterType.THE_EXPERT_POKEMON_BREEDER, ) .withEncounterTier(MysteryEncounterTier.ULTRA) + .withDisallowedChallenges(Challenges.HARDCORE) .withSceneWaveRangeRequirement(25, 180) .withScenePartySizeRequirement(4, 6, true) // Must have at least 4 legal pokemon in party .withIntroSpriteConfigs([]) // These are set in onInit() @@ -139,7 +141,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount }, { speaker: trainerNameKey, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]) .withOnInit(() => { @@ -189,13 +191,13 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount // Dialogue and egg calcs for Pokemon 1 const [pokemon1CommonEggs, pokemon1RareEggs] = calculateEggRewardsForPokemon(pokemon1); - let pokemon1Tooltip = getEncounterText(`${namespace}:option.1.tooltip_base`)!; + let pokemon1Tooltip = getEncounterText(`${namespace}:option.1.tooltipBase`)!; if (pokemon1RareEggs > 0) { const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon1RareEggs, rarity: i18next.t("egg:greatTier"), }); - pokemon1Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { + pokemon1Tooltip += i18next.t(`${namespace}:eggsTooltip`, { eggs: eggsText, }); encounter.setDialogueToken("pokemon1RareEggs", eggsText); @@ -205,7 +207,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount count: pokemon1CommonEggs, rarity: i18next.t("egg:defaultTier"), }); - pokemon1Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { + pokemon1Tooltip += i18next.t(`${namespace}:eggsTooltip`, { eggs: eggsText, }); encounter.setDialogueToken("pokemon1CommonEggs", eggsText); @@ -214,13 +216,13 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount // Dialogue and egg calcs for Pokemon 2 const [pokemon2CommonEggs, pokemon2RareEggs] = calculateEggRewardsForPokemon(pokemon2); - let pokemon2Tooltip = getEncounterText(`${namespace}:option.2.tooltip_base`)!; + let pokemon2Tooltip = getEncounterText(`${namespace}:option.2.tooltipBase`)!; if (pokemon2RareEggs > 0) { const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon2RareEggs, rarity: i18next.t("egg:greatTier"), }); - pokemon2Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { + pokemon2Tooltip += i18next.t(`${namespace}:eggsTooltip`, { eggs: eggsText, }); encounter.setDialogueToken("pokemon2RareEggs", eggsText); @@ -230,7 +232,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount count: pokemon2CommonEggs, rarity: i18next.t("egg:defaultTier"), }); - pokemon2Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { + pokemon2Tooltip += i18next.t(`${namespace}:eggsTooltip`, { eggs: eggsText, }); encounter.setDialogueToken("pokemon2CommonEggs", eggsText); @@ -239,13 +241,13 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount // Dialogue and egg calcs for Pokemon 3 const [pokemon3CommonEggs, pokemon3RareEggs] = calculateEggRewardsForPokemon(pokemon3); - let pokemon3Tooltip = getEncounterText(`${namespace}:option.3.tooltip_base`)!; + let pokemon3Tooltip = getEncounterText(`${namespace}:option.3.tooltipBase`)!; if (pokemon3RareEggs > 0) { const eggsText = i18next.t(`${namespace}:numEggs`, { count: pokemon3RareEggs, rarity: i18next.t("egg:greatTier"), }); - pokemon3Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { + pokemon3Tooltip += i18next.t(`${namespace}:eggsTooltip`, { eggs: eggsText, }); encounter.setDialogueToken("pokemon3RareEggs", eggsText); @@ -255,7 +257,7 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount count: pokemon3CommonEggs, rarity: i18next.t("egg:defaultTier"), }); - pokemon3Tooltip += i18next.t(`${namespace}:eggs_tooltip`, { + pokemon3Tooltip += i18next.t(`${namespace}:eggsTooltip`, { eggs: eggsText, }); encounter.setDialogueToken("pokemon3CommonEggs", eggsText); @@ -321,14 +323,14 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount ]; if (encounter.dialogueTokens.hasOwnProperty("pokemon1CommonEggs")) { encounter.dialogue.outro.push({ - text: i18next.t(`${namespace}:gained_eggs`, { + text: i18next.t(`${namespace}:gainedEggs`, { numEggs: encounter.dialogueTokens["pokemon1CommonEggs"], }), }); } if (encounter.dialogueTokens.hasOwnProperty("pokemon1RareEggs")) { encounter.dialogue.outro.push({ - text: i18next.t(`${namespace}:gained_eggs`, { + text: i18next.t(`${namespace}:gainedEggs`, { numEggs: encounter.dialogueTokens["pokemon1RareEggs"], }), }); @@ -380,14 +382,14 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount ]; if (encounter.dialogueTokens.hasOwnProperty("pokemon2CommonEggs")) { encounter.dialogue.outro.push({ - text: i18next.t(`${namespace}:gained_eggs`, { + text: i18next.t(`${namespace}:gainedEggs`, { numEggs: encounter.dialogueTokens["pokemon2CommonEggs"], }), }); } if (encounter.dialogueTokens.hasOwnProperty("pokemon2RareEggs")) { encounter.dialogue.outro.push({ - text: i18next.t(`${namespace}:gained_eggs`, { + text: i18next.t(`${namespace}:gainedEggs`, { numEggs: encounter.dialogueTokens["pokemon2RareEggs"], }), }); @@ -439,14 +441,14 @@ export const TheExpertPokemonBreederEncounter: MysteryEncounter = MysteryEncount ]; if (encounter.dialogueTokens.hasOwnProperty("pokemon3CommonEggs")) { encounter.dialogue.outro.push({ - text: i18next.t(`${namespace}:gained_eggs`, { + text: i18next.t(`${namespace}:gainedEggs`, { numEggs: encounter.dialogueTokens["pokemon3CommonEggs"], }), }); } if (encounter.dialogueTokens.hasOwnProperty("pokemon3RareEggs")) { encounter.dialogue.outro.push({ - text: i18next.t(`${namespace}:gained_eggs`, { + text: i18next.t(`${namespace}:gainedEggs`, { numEggs: encounter.dialogueTokens["pokemon3RareEggs"], }), }); @@ -482,7 +484,7 @@ function getPartyConfig(): EnemyPartyConfig { trainerType: TrainerType.EXPERT_POKEMON_BREEDER, pokemonConfigs: [ { - nickname: i18next.t(`${namespace}:cleffa_1_nickname`, { + nickname: i18next.t(`${namespace}:cleffa1Nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName(), }), species: getPokemonSpecies(cleffaSpecies), @@ -501,7 +503,7 @@ function getPartyConfig(): EnemyPartyConfig { // All 3 members always Cleffa line, but different configs baseConfig.pokemonConfigs!.push( { - nickname: i18next.t(`${namespace}:cleffa_2_nickname`, { + nickname: i18next.t(`${namespace}:cleffa2Nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName(), }), species: getPokemonSpecies(cleffaSpecies), @@ -514,7 +516,7 @@ function getPartyConfig(): EnemyPartyConfig { ivs: [31, 31, 31, 31, 31, 31], }, { - nickname: i18next.t(`${namespace}:cleffa_3_nickname`, { + nickname: i18next.t(`${namespace}:cleffa3Nickname`, { speciesName: getPokemonSpecies(cleffaSpecies).getName(), }), species: getPokemonSpecies(cleffaSpecies), @@ -647,7 +649,7 @@ function onGameOver() { encounter.dialogue.outro = [ { speaker: trainerNameKey, - text: `${namespace}:outro_failed`, + text: `${namespace}:outroFailed`, }, ]; 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 91662993a51..99f6e671052 100644 --- a/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts @@ -66,7 +66,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui text: `${namespace}:intro`, }, { - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, speaker: `${namespace}:speaker`, }, ]) @@ -178,8 +178,8 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui // Always max price for shiny (flip HA back to normal), and add special messaging priceMultiplier = MAX_POKEMON_PRICE_MULTIPLIER; pokemon.abilityIndex = 0; - encounter.dialogue.encounterOptionsDialogue!.description = `${namespace}:description_shiny`; - encounter.options[0].dialogue!.buttonTooltip = `${namespace}:option.1.tooltip_shiny`; + encounter.dialogue.encounterOptionsDialogue!.description = `${namespace}:descriptionShiny`; + encounter.options[0].dialogue!.buttonTooltip = `${namespace}:option.1.tooltipShiny`; } const price = globalScene.getWaveMoneyAmount(priceMultiplier); encounter.setDialogueToken("purchasePokemon", pokemon.getNameToRender()); @@ -202,7 +202,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui buttonTooltip: `${namespace}:option.1.tooltip`, selected: [ { - text: `${namespace}:option.1.selected_message`, + text: `${namespace}:option.1.selectedMessage`, }, ], }) @@ -215,7 +215,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui updatePlayerMoney(-price, true, false); // Show dialogue - await showEncounterDialogue(`${namespace}:option.1.selected_dialogue`, `${namespace}:speaker`); + await showEncounterDialogue(`${namespace}:option.1.selectedDialogue`, `${namespace}:speaker`); await transitionMysteryEncounterIntroVisuals(); // "Catch" purchased pokemon 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 568dc5de8b1..89bfc659944 100644 --- a/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-strong-stuff-encounter.ts @@ -115,7 +115,7 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder ], tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { - queueEncounterMessage(`${namespace}:option.2.stat_boost`); + queueEncounterMessage(`${namespace}:option.2.statBoost`); globalScene.phaseManager.unshiftNew( "StatStageChangePhase", pokemon.getBattlerIndex(), @@ -181,7 +181,7 @@ export const TheStrongStuffEncounter: MysteryEncounter = MysteryEncounterBuilder encounter.setDialogueToken("reductionValue", HIGH_BST_REDUCTION_VALUE.toString()); encounter.setDialogueToken("increaseValue", BST_INCREASE_VALUE.toString()); - await showEncounterText(`${namespace}:option.1.selected_2`, null, undefined, true); + await showEncounterText(`${namespace}:option.1.selected2`, null, undefined, true); encounter.dialogue.outro = [ { 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 e17bf0575d7..71fe961f053 100644 --- a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts @@ -87,7 +87,7 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter = MysteryEncounter }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]) .withAutoHideIntroVisuals(false) @@ -163,7 +163,7 @@ async function spawnNextTrainerOrEndEncounter() { globalScene.playSound("item_fanfare"); await showEncounterText(i18next.t("battle:rewardGain", { modifierName: newModifier?.type.name })); - await showEncounterDialogue(`${namespace}:victory_2`, `${namespace}:speaker`); + await showEncounterDialogue(`${namespace}:victory2`, `${namespace}:speaker`); globalScene.ui.clearText(); // Clears "Winstrate" title from screen as rewards get animated in const machoBrace = generateModifierTypeOption(modifierTypes.MYSTERY_ENCOUNTER_MACHO_BRACE)!; machoBrace.type.tier = ModifierTier.MASTER; diff --git a/src/data/mystery-encounters/encounters/training-session-encounter.ts b/src/data/mystery-encounters/encounters/training-session-encounter.ts index e56c42a3ee5..b8173aa5fed 100644 --- a/src/data/mystery-encounters/encounters/training-session-encounter.ts +++ b/src/data/mystery-encounters/encounters/training-session-encounter.ts @@ -90,7 +90,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde // Only Pokemon that are not KOed/legal can be trained const selectableFilter = (pokemon: Pokemon) => { - return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalid_selection`); + return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalidSelection`); }; return selectPokemonForOption(onPokemonSelected, undefined, selectableFilter); @@ -174,7 +174,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde .withDialogue({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - secondOptionPrompt: `${namespace}:option.2.select_prompt`, + secondOptionPrompt: `${namespace}:option.2.selectPrompt`, selected: [ { text: `${namespace}:option.selected`, @@ -205,7 +205,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde // Only Pokemon that are not KOed/legal can be trained const selectableFilter = (pokemon: Pokemon) => { - return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalid_selection`); + return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalidSelection`); }; return selectPokemonForOption(onPokemonSelected, undefined, selectableFilter); @@ -248,7 +248,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - secondOptionPrompt: `${namespace}:option.3.select_prompt`, + secondOptionPrompt: `${namespace}:option.3.selectPrompt`, selected: [ { text: `${namespace}:option.selected`, @@ -295,7 +295,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde // Only Pokemon that are not KOed/legal can be trained const selectableFilter = (pokemon: Pokemon) => { - return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalid_selection`); + return isPokemonValidForEncounterOptionSelection(pokemon, `${namespace}:invalidSelection`); }; return selectPokemonForOption(onPokemonSelected, undefined, selectableFilter); 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 74a36a280d3..af576ffd8be 100644 --- a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts +++ b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts @@ -153,7 +153,7 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde doGarbageDig(); }) .withOptionPhase(async () => { - // Gain 2 Leftovers and 1 Shell Bell + // Gain 1 Leftovers and 1 Shell Bell await transitionMysteryEncounterIntroVisuals(); await tryApplyDigRewardItems(); @@ -194,7 +194,7 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde .withOptionPhase(async () => { // Investigate garbage, battle Gmax Garbodor globalScene.setFieldScale(0.75); - await showEncounterText(`${namespace}:option.2.selected_2`); + await showEncounterText(`${namespace}:option.2.selected2`); await transitionMysteryEncounterIntroVisuals(); const encounter = globalScene.currentBattle.mysteryEncounter!; @@ -231,21 +231,7 @@ async function tryApplyDigRewardItems() { const party = globalScene.getPlayerParty(); // Iterate over the party until an item was successfully given - // First leftovers - for (const pokemon of party) { - const heldItems = globalScene.findModifiers( - m => m instanceof PokemonHeldItemModifier && m.pokemonId === pokemon.id, - true, - ) as PokemonHeldItemModifier[]; - const existingLeftovers = heldItems.find(m => m instanceof TurnHealModifier) as TurnHealModifier; - - if (!existingLeftovers || existingLeftovers.getStackCount() < existingLeftovers.getMaxStackCount()) { - await applyModifierTypeToPlayerPokemon(pokemon, leftovers); - break; - } - } - - // Second leftovers + // Only Leftovers for (const pokemon of party) { const heldItems = globalScene.findModifiers( m => m instanceof PokemonHeldItemModifier && m.pokemonId === pokemon.id, diff --git a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts index c9e2ffedeec..6aeff852de7 100644 --- a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts +++ b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts @@ -97,7 +97,7 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder. isBoss: false, tags: [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON], mysteryEncounterBattleEffects: (pokemon: Pokemon) => { - queueEncounterMessage(`${namespace}:option.1.stat_boost`); + queueEncounterMessage(`${namespace}:option.1.statBoost`); globalScene.phaseManager.unshiftNew( "StatStageChangePhase", pokemon.getBattlerIndex(), @@ -191,7 +191,7 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder. .withDialogue({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.2.disabledTooltip`, selected: [ { text: `${namespace}:option.2.selected`, @@ -236,7 +236,7 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder. .withDialogue({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, selected: [ { text: `${namespace}:option.3.selected`, diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index 57b066e2ba2..790bdf0dbef 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -143,7 +143,7 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]) .setLocalizationKey(`${namespace}`) @@ -216,7 +216,7 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit await cutsceneDialoguePromise; doHideDreamBackground(); - await showEncounterText(`${namespace}:option.1.dream_complete`); + await showEncounterText(`${namespace}:option.1.dreamComplete`); await doNewTeamPostProcess(transformations); setEncounterRewards({ @@ -329,7 +329,7 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit onBeforeRewards, ); - await showEncounterText(`${namespace}:option.2.selected_2`, null, undefined, true); + await showEncounterText(`${namespace}:option.2.selected2`, null, undefined, true); await initBattleWithEnemyConfig(enemyPartyConfig); }, ) diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index b599f923534..5c976cbc8cd 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -467,7 +467,7 @@ export function updatePlayerMoney(changeValue: number, playSound = true, showMes if (showMessage) { if (changeValue < 0) { globalScene.phaseManager.queueMessage( - i18next.t("mysteryEncounterMessages:paid_money", { + i18next.t("mysteryEncounterMessages:paidMoney", { amount: -changeValue, }), null, @@ -475,7 +475,7 @@ export function updatePlayerMoney(changeValue: number, playSound = true, showMes ); } else { globalScene.phaseManager.queueMessage( - i18next.t("mysteryEncounterMessages:receive_money", { + i18next.t("mysteryEncounterMessages:receiveMoney", { amount: changeValue, }), null, @@ -587,7 +587,7 @@ export function selectPokemonForOption( return true; }, onHover: () => { - showEncounterText(i18next.t("mysteryEncounterMessages:cancel_option"), 0, 0, false); + showEncounterText(i18next.t("mysteryEncounterMessages:cancelOption"), 0, 0, false); }, }); @@ -720,7 +720,7 @@ export function selectOptionThenPokemon( if (onHoverOverCancelOption) { onHoverOverCancelOption(); } - showEncounterText(i18next.t("mysteryEncounterMessages:cancel_option"), 0, 0, false); + showEncounterText(i18next.t("mysteryEncounterMessages:cancelOption"), 0, 0, false); }, }); diff --git a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts index 0c6a8e25452..93ef59d6ee7 100644 --- a/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-pokemon-utils.ts @@ -309,7 +309,7 @@ export function getRandomSpeciesByStarterCost( */ export function koPlayerPokemon(pokemon: PlayerPokemon) { pokemon.hp = 0; - pokemon.trySetStatus(StatusEffect.FAINT); + pokemon.doSetStatus(StatusEffect.FAINT); pokemon.updateInfo(); queueEncounterMessage( i18next.t("battle:fainted", { diff --git a/src/data/nature.ts b/src/data/nature.ts index b085faebb80..65e401cd288 100644 --- a/src/data/nature.ts +++ b/src/data/nature.ts @@ -3,7 +3,7 @@ import { EFFECTIVE_STATS, getShortenedStatKey, Stat } from "#enums/stat"; import { TextStyle } from "#enums/text-style"; import { UiTheme } from "#enums/ui-theme"; import { getBBCodeFrag } from "#ui/text"; -import { toTitleCase } from "#utils/strings"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; export function getNatureName( @@ -13,7 +13,7 @@ export function getNatureName( ignoreBBCode = false, uiTheme: UiTheme = UiTheme.DEFAULT, ): string { - let ret = toTitleCase(Nature[nature]); + let ret = toCamelCase(Nature[nature]); //Translating nature if (i18next.exists(`nature:${ret}`)) { ret = i18next.t(`nature:${ret}` as any); diff --git a/src/data/pokemon-forms/form-change-triggers.ts b/src/data/pokemon-forms/form-change-triggers.ts index c24466eb5ec..7c042b27058 100644 --- a/src/data/pokemon-forms/form-change-triggers.ts +++ b/src/data/pokemon-forms/form-change-triggers.ts @@ -30,7 +30,7 @@ export abstract class SpeciesFormChangeTrigger { export class SpeciesFormChangeManualTrigger extends SpeciesFormChangeTrigger {} export class SpeciesFormChangeAbilityTrigger extends SpeciesFormChangeTrigger { - public description: string = i18next.t("pokemonEvolutions:Forms.ability"); + public description: string = i18next.t("pokemonEvolutions:forms.ability"); } export class SpeciesFormChangeCompoundTrigger { @@ -69,10 +69,10 @@ export class SpeciesFormChangeItemTrigger extends SpeciesFormChangeTrigger { this.item = item; this.active = active; this.description = this.active - ? i18next.t("pokemonEvolutions:Forms.item", { + ? i18next.t("pokemonEvolutions:forms.item", { item: i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.item]}`), }) - : i18next.t("pokemonEvolutions:Forms.deactivateItem", { + : i18next.t("pokemonEvolutions:forms.deactivateItem", { item: i18next.t(`modifierType:FormChangeItem.${FormChangeItem[this.item]}`), }); } @@ -97,7 +97,7 @@ export class SpeciesFormChangeTimeOfDayTrigger extends SpeciesFormChangeTrigger constructor(...timesOfDay: TimeOfDay[]) { super(); this.timesOfDay = timesOfDay; - this.description = i18next.t("pokemonEvolutions:Forms.timeOfDay"); + this.description = i18next.t("pokemonEvolutions:orms.timeOfDay"); } canChange(_pokemon: Pokemon): boolean { @@ -111,8 +111,8 @@ export class SpeciesFormChangeActiveTrigger extends SpeciesFormChangeTrigger { super(); this.active = active; this.description = this.active - ? i18next.t("pokemonEvolutions:Forms.enter") - : i18next.t("pokemonEvolutions:Forms.leave"); + ? i18next.t("pokemonEvolutions:forms.enter") + : i18next.t("pokemonEvolutions:forms.leave"); } canChange(pokemon: Pokemon): boolean { @@ -128,7 +128,7 @@ export class SpeciesFormChangeStatusEffectTrigger extends SpeciesFormChangeTrigg super(); this.statusEffects = coerceArray(statusEffects); this.invert = invert; - // this.description = i18next.t("pokemonEvolutions:Forms.statusEffect"); + // this.description = i18next.t("pokemonEvolutions:forms.statusEffect"); } canChange(pokemon: Pokemon): boolean { @@ -146,10 +146,10 @@ export class SpeciesFormChangeMoveLearnedTrigger extends SpeciesFormChangeTrigge this.known = known; const moveKey = toCamelCase(MoveId[this.move]); this.description = known - ? i18next.t("pokemonEvolutions:Forms.moveLearned", { + ? i18next.t("pokemonEvolutions:forms.moveLearned", { move: i18next.t(`move:${moveKey}.name`), }) - : i18next.t("pokemonEvolutions:Forms.moveForgotten", { + : i18next.t("pokemonEvolutions:forms.moveForgotten", { move: i18next.t(`move:${moveKey}.name`), }); } @@ -171,7 +171,7 @@ export abstract class SpeciesFormChangeMoveTrigger extends SpeciesFormChangeTrig } export class SpeciesFormChangePreMoveTrigger extends SpeciesFormChangeMoveTrigger { - description = i18next.t("pokemonEvolutions:Forms.preMove"); + description = i18next.t("pokemonEvolutions:forms.preMove"); canChange(pokemon: Pokemon): boolean { const command = globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]; return !!command?.move && this.movePredicate(command.move.move) === this.used; @@ -179,7 +179,7 @@ export class SpeciesFormChangePreMoveTrigger extends SpeciesFormChangeMoveTrigge } export class SpeciesFormChangePostMoveTrigger extends SpeciesFormChangeMoveTrigger { - description = i18next.t("pokemonEvolutions:Forms.postMove"); + description = i18next.t("pokemonEvolutions:forms.postMove"); canChange(pokemon: Pokemon): boolean { return ( pokemon.summonData && !!pokemon.getLastXMoves(1).filter(m => this.movePredicate(m.move)).length === this.used @@ -244,7 +244,7 @@ export class SpeciesFormChangeWeatherTrigger extends SpeciesFormChangeTrigger { super(); this.ability = ability; this.weathers = weathers; - this.description = i18next.t("pokemonEvolutions:Forms.weather"); + this.description = i18next.t("pokemonEvolutions:forms.weather"); } /** @@ -282,7 +282,7 @@ export class SpeciesFormChangeRevertWeatherFormTrigger extends SpeciesFormChange super(); this.ability = ability; this.weathers = weathers; - this.description = i18next.t("pokemonEvolutions:Forms.weatherRevert"); + this.description = i18next.t("pokemonEvolutions:forms.weatherRevert"); } /** diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 7bfe02d9086..064ad57cfb3 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -778,7 +778,7 @@ export class PokemonSpecies extends PokemonSpeciesForm implements Localizable { } if (key) { - return i18next.t(`battlePokemonForm:${key}`, { + return i18next.t(`battlePokemonForm:${toCamelCase(key)}`, { pokemonName: this.name, }); } @@ -810,7 +810,9 @@ export class PokemonSpecies extends PokemonSpeciesForm implements Localizable { return this.name; // Other special cases could be put here too } // Everything beyond this point essentially follows the pattern of FORMNAME_SPECIES - return i18next.t(`pokemonForm:appendForm.${SpeciesId[this.speciesId].split("_")[0]}`, { pokemonName: this.name }); + return i18next.t(`pokemonForm:appendForm.${toCamelCase(SpeciesId[this.speciesId].split("_")[0])}`, { + pokemonName: this.name, + }); } /** @@ -827,7 +829,7 @@ export class PokemonSpecies extends PokemonSpeciesForm implements Localizable { const region = this.getRegion(); if (this.speciesId === SpeciesId.ARCEUS) { - ret = i18next.t(`pokemonInfo:Type.${formText.toUpperCase()}`); + ret = i18next.t(`pokemonInfo:type.${toCamelCase(formText)}`); } else if ( [ SpeciesFormKey.MEGA, @@ -841,8 +843,8 @@ export class PokemonSpecies extends PokemonSpeciesForm implements Localizable { ].includes(formKey as SpeciesFormKey) ) { return append - ? i18next.t(`battlePokemonForm:${formKey}`, { pokemonName: this.name }) - : i18next.t(`pokemonForm:battleForm.${formKey}`); + ? i18next.t(`battlePokemonForm:${toCamelCase(formKey)}`, { pokemonName: this.name }) + : i18next.t(`pokemonForm:battleForm.${toCamelCase(formKey)}`); } else if ( region === Region.NORMAL || (this.speciesId === SpeciesId.GALAR_DARMANITAN && formIndex > 0) || @@ -868,10 +870,10 @@ export class PokemonSpecies extends PokemonSpeciesForm implements Localizable { return i18next.t("pokemonForm:ursalunaBloodmoon"); } else { // Only regional forms should be left at this point - return i18next.t(`pokemonForm:regionalForm.${Region[region]}`); + return i18next.t(`pokemonForm:regionalForm.${toCamelCase(Region[region])}`); } return append - ? i18next.t("pokemonForm:appendForm.GENERIC", { + ? i18next.t("pokemonForm:appendForm.generic", { pokemonName: this.name, formName: ret, }) @@ -879,8 +881,8 @@ export class PokemonSpecies extends PokemonSpeciesForm implements Localizable { } localize(): void { - this.name = i18next.t(`pokemon:${SpeciesId[this.speciesId].toLowerCase()}`); - this.category = i18next.t(`pokemonCategory:${SpeciesId[this.speciesId].toLowerCase()}_category`); + this.name = i18next.t(`pokemon:${toCamelCase(SpeciesId[this.speciesId])}`); + this.category = i18next.t(`pokemonCategory:${toCamelCase(SpeciesId[this.speciesId])}Category`); } getWildSpeciesForLevel(level: number, allowEvolving: boolean, isBoss: boolean, gameMode: GameMode): SpeciesId { diff --git a/src/data/splash-messages.ts b/src/data/splash-messages.ts index 3223bbb019e..55ba185bfb2 100644 --- a/src/data/splash-messages.ts +++ b/src/data/splash-messages.ts @@ -100,7 +100,7 @@ const commonSplashMessages = [ "liveWoChienReaction", "itsAFeatureNotABug", "theEggsAreNotForEating", - "7.8outOf10TooManyWaterBiomes", + "tooManyWaterBiomes", "butNothingHappened", "thePowerOfScienceIsAmazing", "freeToPlay", @@ -152,7 +152,7 @@ const commonSplashMessages = [ "insertTextHere", "endingEndlessNotFound", "iLikeMyEggsVouchered", - "YOU", + "you", "noAddedSugar", "notSponsored", "notRated", diff --git a/src/data/trainer-names.ts b/src/data/trainer-names.ts deleted file mode 100644 index 8eafd9f6404..00000000000 --- a/src/data/trainer-names.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { TrainerType } from "#enums/trainer-type"; -import { toPascalSnakeCase } from "#utils/strings"; - -class TrainerNameConfig { - public urls: string[]; - public femaleUrls: string[] | null; - - constructor(type: TrainerType, ...urls: string[]) { - this.urls = urls.length ? urls : [toPascalSnakeCase(TrainerType[type])]; - } - - hasGenderVariant(...femaleUrls: string[]): TrainerNameConfig { - this.femaleUrls = femaleUrls.length ? femaleUrls : null; - return this; - } -} - -interface TrainerNameConfigs { - [key: number]: TrainerNameConfig; -} - -// used in a commented code -// biome-ignore lint/correctness/noUnusedVariables: Used by commented code -const trainerNameConfigs: TrainerNameConfigs = { - [TrainerType.ACE_TRAINER]: new TrainerNameConfig(TrainerType.ACE_TRAINER), - [TrainerType.ARTIST]: new TrainerNameConfig(TrainerType.ARTIST), - [TrainerType.BACKERS]: new TrainerNameConfig(TrainerType.BACKERS), - [TrainerType.BACKPACKER]: new TrainerNameConfig(TrainerType.BACKPACKER), - [TrainerType.BAKER]: new TrainerNameConfig(TrainerType.BAKER), - [TrainerType.BEAUTY]: new TrainerNameConfig(TrainerType.BEAUTY), - [TrainerType.BIKER]: new TrainerNameConfig(TrainerType.BIKER), - [TrainerType.BLACK_BELT]: new TrainerNameConfig(TrainerType.BLACK_BELT).hasGenderVariant("Battle_Girl"), - [TrainerType.BREEDER]: new TrainerNameConfig(TrainerType.BREEDER, "Pokémon_Breeder"), - [TrainerType.CLERK]: new TrainerNameConfig(TrainerType.CLERK), - [TrainerType.CYCLIST]: new TrainerNameConfig(TrainerType.CYCLIST), - [TrainerType.DANCER]: new TrainerNameConfig(TrainerType.DANCER), - [TrainerType.DEPOT_AGENT]: new TrainerNameConfig(TrainerType.DEPOT_AGENT), - [TrainerType.DOCTOR]: new TrainerNameConfig(TrainerType.DOCTOR).hasGenderVariant("Nurse"), - [TrainerType.FIREBREATHER]: new TrainerNameConfig(TrainerType.FIREBREATHER), - [TrainerType.FISHERMAN]: new TrainerNameConfig(TrainerType.FISHERMAN), - [TrainerType.GUITARIST]: new TrainerNameConfig(TrainerType.GUITARIST), - [TrainerType.HARLEQUIN]: new TrainerNameConfig(TrainerType.HARLEQUIN), - [TrainerType.HIKER]: new TrainerNameConfig(TrainerType.HIKER), - [TrainerType.HOOLIGANS]: new TrainerNameConfig(TrainerType.HOOLIGANS), - [TrainerType.HOOPSTER]: new TrainerNameConfig(TrainerType.HOOPSTER), - [TrainerType.INFIELDER]: new TrainerNameConfig(TrainerType.INFIELDER), - [TrainerType.JANITOR]: new TrainerNameConfig(TrainerType.JANITOR), - [TrainerType.LINEBACKER]: new TrainerNameConfig(TrainerType.LINEBACKER), - [TrainerType.MAID]: new TrainerNameConfig(TrainerType.MAID), - [TrainerType.MUSICIAN]: new TrainerNameConfig(TrainerType.MUSICIAN), - [TrainerType.HEX_MANIAC]: new TrainerNameConfig(TrainerType.HEX_MANIAC), - [TrainerType.NURSERY_AIDE]: new TrainerNameConfig(TrainerType.NURSERY_AIDE), - [TrainerType.OFFICER]: new TrainerNameConfig(TrainerType.OFFICER), - [TrainerType.PARASOL_LADY]: new TrainerNameConfig(TrainerType.PARASOL_LADY), - [TrainerType.PILOT]: new TrainerNameConfig(TrainerType.PILOT), - [TrainerType.POKEFAN]: new TrainerNameConfig(TrainerType.POKEFAN, "Poké_Fan"), - [TrainerType.PRESCHOOLER]: new TrainerNameConfig(TrainerType.PRESCHOOLER), - [TrainerType.PSYCHIC]: new TrainerNameConfig(TrainerType.PSYCHIC), - [TrainerType.RANGER]: new TrainerNameConfig(TrainerType.RANGER), - [TrainerType.RICH]: new TrainerNameConfig(TrainerType.RICH, "Gentleman").hasGenderVariant("Madame"), - [TrainerType.RICH_KID]: new TrainerNameConfig(TrainerType.RICH_KID, "Rich_Boy").hasGenderVariant("Lady"), - [TrainerType.ROUGHNECK]: new TrainerNameConfig(TrainerType.ROUGHNECK), - [TrainerType.SAILOR]: new TrainerNameConfig(TrainerType.SAILOR), - [TrainerType.SCIENTIST]: new TrainerNameConfig(TrainerType.SCIENTIST), - [TrainerType.SMASHER]: new TrainerNameConfig(TrainerType.SMASHER), - [TrainerType.SNOW_WORKER]: new TrainerNameConfig(TrainerType.SNOW_WORKER, "Worker"), - [TrainerType.STRIKER]: new TrainerNameConfig(TrainerType.STRIKER), - [TrainerType.SCHOOL_KID]: new TrainerNameConfig(TrainerType.SCHOOL_KID, "School_Kid"), - [TrainerType.SWIMMER]: new TrainerNameConfig(TrainerType.SWIMMER), - [TrainerType.TWINS]: new TrainerNameConfig(TrainerType.TWINS), - [TrainerType.VETERAN]: new TrainerNameConfig(TrainerType.VETERAN), - [TrainerType.WAITER]: new TrainerNameConfig(TrainerType.WAITER).hasGenderVariant("Waitress"), - [TrainerType.WORKER]: new TrainerNameConfig(TrainerType.WORKER), - [TrainerType.YOUNGSTER]: new TrainerNameConfig(TrainerType.YOUNGSTER).hasGenderVariant("Lass"), -}; - -// function used in a commented code -// biome-ignore lint/correctness/noUnusedVariables: TODO make this into a script instead of having it be in src/data... -function fetchAndPopulateTrainerNames( - url: string, - parser: DOMParser, - trainerNames: Set, - femaleTrainerNames: Set, - forceFemale = false, -) { - return new Promise(resolve => { - fetch(`https://bulbapedia.bulbagarden.net/wiki/${url}_(Trainer_class)`) - .then(response => response.text()) - .then(html => { - console.log(url); - const htmlDoc = parser.parseFromString(html, "text/html"); - const trainerListHeader = htmlDoc.querySelector("#Trainer_list")?.parentElement; - if (!trainerListHeader) { - return []; - } - 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 => { - if (t.nodeName !== "TABLE" || t["className"] !== "expandable") { - return false; - } - const childIndex = elements.indexOf(t); - return childIndex > startChildIndex && childIndex < endChildIndex; - }) - .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); - for (const row of trainerRows) { - const nameCell = row.firstElementChild; - if (!nameCell) { - continue; - } - const content = nameCell.innerHTML; - if (content.indexOf(" -1) { - const female = /♀/.test(content); - if (url === "Twins") { - console.log(content); - } - const nameMatch = />([a-z]+(?: & [a-z]+)?)<\/a>/i.exec(content); - if (nameMatch) { - (female || forceFemale ? femaleTrainerNames : trainerNames).add(nameMatch[1].replace("&", "&")); - } - } - } - } - resolve(); - }); - }); -} - -/*export function scrapeTrainerNames() { - const parser = new DOMParser(); - const trainerTypeNames = {}; - const populateTrainerNamePromises: Promise[] = []; - for (let t of Object.keys(trainerNameConfigs)) { - populateTrainerNamePromises.push(new Promise(resolve => { - const trainerType = t; - trainerTypeNames[trainerType] = []; - - const config = trainerNameConfigs[t] as TrainerNameConfig; - const trainerNames = new Set(); - const femaleTrainerNames = new Set(); - console.log(config.urls, config.femaleUrls) - const trainerClassRequests = config.urls.map(u => fetchAndPopulateTrainerNames(u, parser, trainerNames, femaleTrainerNames)); - if (config.femaleUrls) - trainerClassRequests.push(...config.femaleUrls.map(u => fetchAndPopulateTrainerNames(u, parser, null, femaleTrainerNames, true))); - Promise.all(trainerClassRequests).then(() => { - console.log(trainerNames, femaleTrainerNames) - trainerTypeNames[trainerType] = !femaleTrainerNames.size ? Array.from(trainerNames) : [ Array.from(trainerNames), Array.from(femaleTrainerNames) ]; - resolve(); - }); - })); - } - Promise.all(populateTrainerNamePromises).then(() => { - let output = 'export const trainerNamePools = {'; - Object.keys(trainerTypeNames).forEach(t => { - output += `\n\t[TrainerType.${TrainerType[t]}]: ${JSON.stringify(trainerTypeNames[t])},`; - }); - output += `\n};`; - console.log(output); - }); -}*/ diff --git a/src/data/trainers/trainer-config.ts b/src/data/trainers/trainer-config.ts index 67618df1ddd..f0042e0af91 100644 --- a/src/data/trainers/trainer-config.ts +++ b/src/data/trainers/trainer-config.ts @@ -43,7 +43,7 @@ import type { } from "#types/trainer-funcs"; import { coerceArray, isNullOrUndefined, randSeedInt, randSeedIntRange, randSeedItem } from "#utils/common"; import { getPokemonSpecies } from "#utils/pokemon-utils"; -import { toSnakeCase, toTitleCase } from "#utils/strings"; +import { toCamelCase, toTitleCase } from "#utils/strings"; import i18next from "i18next"; /** Minimum BST for Pokemon generated onto the Elite Four's teams */ @@ -193,8 +193,7 @@ export class TrainerConfig { initI18n(); } - // Make the title lowercase and replace spaces with underscores - title = title.toLowerCase().replace(/\s/g, "_"); + title = toCamelCase(title); // Get the title from the i18n file this.title = i18next.t(`titles:${title}`); @@ -288,7 +287,7 @@ export class TrainerConfig { initI18n(); } // Set the localized name for the female rival. - this.nameFemale = i18next.t("trainerNames:rival_female"); + this.nameFemale = i18next.t("trainerNames:rivalFemale"); } else { // Otherwise, assign the provided female name. this.nameFemale = nameFemale!; // TODO: is this bang correct? @@ -365,8 +364,7 @@ export class TrainerConfig { initI18n(); } - // Make the title lowercase and replace spaces with underscores - titleDouble = titleDouble.toLowerCase().replace(/\s/g, "_"); + titleDouble = toCamelCase(titleDouble); // Get the title from the i18n file this.titleDouble = i18next.t(`titles:${titleDouble}`); @@ -552,7 +550,7 @@ export class TrainerConfig { this.setPartyMemberFunc(-(s + 1), getRandomPartyMemberFunc(coerceArray(speciesPool))); }); - const nameForCall = this.name.toLowerCase().replace(/\s/g, "_"); + const nameForCall = toCamelCase(this.name); this.name = i18next.t(`trainerNames:${nameForCall}`); this.setHasVoucher(false); this.setTitle(title); @@ -577,7 +575,7 @@ export class TrainerConfig { this.setPartyTemplates(trainerPartyTemplates.ELITE_FOUR); - const nameForCall = this.name.toLowerCase().replace(/\s/g, "_"); + const nameForCall = toCamelCase(this.name); this.name = i18next.t(`trainerNames:${nameForCall}`); this.setMoneyMultiplier(2); this.setBoss(); @@ -618,7 +616,7 @@ export class TrainerConfig { this.setSpeciesFilter(p => p.isOfType(specialtyType)); this.setSpecialtyType(specialtyType); } - const nameForCall = this.name.toLowerCase().replace(/\s/g, "_"); + const nameForCall = toCamelCase(this.name); this.name = i18next.t(`trainerNames:${nameForCall}`); this.setTitle(title); this.setMoneyMultiplier(2.5); @@ -665,14 +663,14 @@ export class TrainerConfig { this.setSpeciesFilter(p => p.isOfType(specialtyType)); this.setSpecialtyType(specialtyType); - // Localize the trainer's name by converting it to lowercase and replacing spaces with underscores. - const nameForCall = this.name.toLowerCase().replace(/\s/g, "_"); + // Localize the trainer's name by converting it to camel case. + const nameForCall = toCamelCase(this.name); this.name = i18next.t(`trainerNames:${nameForCall}`); - // Set the title to "gym_leader". (this is the key in the i18n file) - this.setTitle("gym_leader"); + // Set the title to "gymLeader". (this is the key in the i18n file) + this.setTitle("gymLeader"); if (!isMale) { - this.setTitle("gym_leader_female"); + this.setTitle("gymLeaderFemale"); } // Configure various properties for the Gym Leader. @@ -726,14 +724,14 @@ export class TrainerConfig { this.setSpeciesFilter(p => p.baseTotal >= ELITE_FOUR_MINIMUM_BST); } - // Localize the trainer's name by converting it to lowercase and replacing spaces with underscores. - const nameForCall = toSnakeCase(this.name); + // Localize the trainer's name by converting it to camel case. + const nameForCall = toCamelCase(this.name); this.name = i18next.t(`trainerNames:${nameForCall}`); // Set the title to "elite_four". (this is the key in the i18n file) - this.setTitle("elite_four"); + this.setTitle("eliteFour"); if (!isMale) { - this.setTitle("elite_four_female"); + this.setTitle("eliteFourFemale"); } // Configure various properties for the Elite Four member. @@ -763,14 +761,14 @@ export class TrainerConfig { // Set the party templates for the Champion. this.setPartyTemplates(trainerPartyTemplates.CHAMPION); - // Localize the trainer's name by converting it to lowercase and replacing spaces with underscores. - const nameForCall = this.name.toLowerCase().replace(/\s/g, "_"); + // Localize the trainer's name by converting it to camel case. + const nameForCall = toCamelCase(this.name); this.name = i18next.t(`trainerNames:${nameForCall}`); // Set the title to "champion". (this is the key in the i18n file) this.setTitle("champion"); if (!isMale) { - this.setTitle("champion_female"); + this.setTitle("championFemale"); } // Configure various properties for the Champion. @@ -794,7 +792,7 @@ export class TrainerConfig { if (!getIsInitialized()) { initI18n(); } - this.name = i18next.t(`trainerNames:${name.toLowerCase().replace(/\s/g, "_")}`); + this.name = i18next.t(`trainerNames:${toCamelCase(name)}`); return this; } @@ -830,9 +828,9 @@ export class TrainerConfig { initI18n(); } // Check if the female version exists in the i18n file - if (i18next.exists(`trainerClasses:${this.name.toLowerCase()}`)) { + if (i18next.exists(`trainerClasses:${toCamelCase(this.name)}Female`)) { // If it does, return - return ret + "_female"; + return ret + "Female"; } } } @@ -1348,11 +1346,12 @@ export const trainerConfigs: TrainerConfigs = { [TrainerPoolTier.RARE]: [ SpeciesId.YANMA, SpeciesId.NINJASK, - SpeciesId.WHIRLIPEDE, + SpeciesId.VENIPEDE, SpeciesId.EMOLGA, SpeciesId.SKIDDO, + SpeciesId.ROLYCOLY, ], - [TrainerPoolTier.SUPER_RARE]: [SpeciesId.ACCELGOR, SpeciesId.DREEPY], + [TrainerPoolTier.SUPER_RARE]: [SpeciesId.SHELMET, SpeciesId.DREEPY], }), [TrainerType.DANCER]: new TrainerConfig(++t) .setMoneyMultiplier(1.55) @@ -1398,7 +1397,6 @@ export const trainerConfigs: TrainerConfigs = { trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.THREE_WEAK_SAME, trainerPartyTemplates.ONE_STRONG, - trainerPartyTemplates.SIX_WEAKER, ) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ @@ -1512,7 +1510,6 @@ export const trainerConfigs: TrainerConfigs = { .setMoneyMultiplier(1.1) .setEncounterBgm(TrainerType.POKEFAN) .setPartyTemplates( - trainerPartyTemplates.FOUR_WEAKER, trainerPartyTemplates.THREE_WEAK, trainerPartyTemplates.TWO_WEAK_ONE_AVG, trainerPartyTemplates.TWO_AVG, @@ -1552,7 +1549,7 @@ export const trainerConfigs: TrainerConfigs = { ], [TrainerPoolTier.UNCOMMON]: [SpeciesId.HOUNDOUR, SpeciesId.ROCKRUFF, SpeciesId.MASCHIFF], [TrainerPoolTier.RARE]: [SpeciesId.JOLTEON, SpeciesId.RIOLU], - [TrainerPoolTier.SUPER_RARE]: [], + [TrainerPoolTier.SUPER_RARE]: [SpeciesId.SLAKOTH], [TrainerPoolTier.ULTRA_RARE]: [SpeciesId.ENTEI, SpeciesId.SUICUNE, SpeciesId.RAIKOU], }), [TrainerType.PARASOL_LADY]: new TrainerConfig(++t) @@ -1597,13 +1594,10 @@ export const trainerConfigs: TrainerConfigs = { .setHasDouble("Pokéfan Family") .setEncounterBgm(TrainerType.POKEFAN) .setPartyTemplates( - trainerPartyTemplates.SIX_WEAKER, trainerPartyTemplates.FOUR_WEAK, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.ONE_STRONG, - trainerPartyTemplates.FOUR_WEAK_SAME, trainerPartyTemplates.FIVE_WEAK, - trainerPartyTemplates.SIX_WEAKER_SAME, ) .setSpeciesFilter(s => tmSpecies[MoveId.HELPING_HAND].indexOf(s.speciesId) > -1), [TrainerType.PRESCHOOLER]: new TrainerConfig(++t) @@ -1611,12 +1605,7 @@ export const trainerConfigs: TrainerConfigs = { .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, - ) + .setPartyTemplates(trainerPartyTemplates.THREE_WEAK, trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ SpeciesId.CATERPIE, @@ -1750,11 +1739,7 @@ export const trainerConfigs: TrainerConfigs = { .setHasGenders("Lady") .setHasDouble("Rich Kids") .setEncounterBgm(TrainerType.RICH) - .setPartyTemplates( - trainerPartyTemplates.FOUR_WEAKER, - trainerPartyTemplates.THREE_WEAK_SAME, - trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, - ) + .setPartyTemplates(trainerPartyTemplates.THREE_WEAK_SAME, trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG) .setSpeciesFilter(s => s.baseTotal <= 460), [TrainerType.ROUGHNECK]: new TrainerConfig(++t) .setMoneyMultiplier(1.4) @@ -1868,6 +1853,7 @@ export const trainerConfigs: TrainerConfigs = { SpeciesId.METAPOD, SpeciesId.LEDYBA, SpeciesId.CLEFFA, + SpeciesId.MAREEP, SpeciesId.WOOPER, SpeciesId.TEDDIURSA, SpeciesId.REMORAID, @@ -1879,6 +1865,7 @@ export const trainerConfigs: TrainerConfigs = { SpeciesId.BONSLY, SpeciesId.PETILIL, SpeciesId.SPRITZEE, + SpeciesId.BOUNSWEET, SpeciesId.MILCERY, SpeciesId.PICHU, ]), @@ -1890,6 +1877,7 @@ export const trainerConfigs: TrainerConfigs = { SpeciesId.KAKUNA, SpeciesId.SPINARAK, SpeciesId.IGGLYBUFF, + SpeciesId.MAREEP, SpeciesId.PALDEA_WOOPER, SpeciesId.PHANPY, SpeciesId.MANTYKE, @@ -1901,6 +1889,7 @@ export const trainerConfigs: TrainerConfigs = { SpeciesId.MIME_JR, SpeciesId.COTTONEE, SpeciesId.SWIRLIX, + SpeciesId.FOMANTIS, SpeciesId.FIDOUGH, SpeciesId.EEVEE, ], @@ -3838,7 +3827,7 @@ export const trainerConfigs: TrainerConfigs = { p.setBoss(true, 2); }), ) - .setInstantTera(2), // Tera Fire Arcanine, Tera Grass Exeggutor, Tera Water Gyarados + .setInstantTera(1), // Tera Fire Arcanine, Tera Grass Exeggutor, Tera Water Gyarados [TrainerType.RED]: new TrainerConfig(++t) .initForChampion(true) .setBattleBgm("battle_johto_champion") @@ -4027,19 +4016,14 @@ export const trainerConfigs: TrainerConfigs = { .setBattleBgm("battle_sinnoh_champion") .setMixedBattleBgm("battle_sinnoh_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.SPIRITOMB])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.MILOTIC, SpeciesId.ROSERADE, SpeciesId.HISUI_ARCANINE])) .setPartyMemberFunc( - 1, - getRandomPartyMemberFunc( - [SpeciesId.MILOTIC, SpeciesId.ROSERADE, SpeciesId.HISUI_ARCANINE], - TrainerSlot.TRAINER, - true, - p => { - p.generateAndPopulateMoveset(); - p.teraType = p.species.type1; - }, - ), + 2, + getRandomPartyMemberFunc([SpeciesId.TOGEKISS], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.teraType = p.species.type1; + }), ) - .setPartyMemberFunc(2, getRandomPartyMemberFunc([SpeciesId.TOGEKISS])) .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.LUCARIO])) .setPartyMemberFunc( 4, @@ -4058,7 +4042,7 @@ export const trainerConfigs: TrainerConfigs = { p.setBoss(true, 2); }), ) - .setInstantTera(1), // Tera Water Milotic / Grass Roserade / Fire Hisuian Arcanine + .setInstantTera(2), // Tera Fairy Togekiss [TrainerType.ALDER]: new TrainerConfig(++t) .initForChampion(true) .setHasDouble("alder_iris_double") @@ -5811,7 +5795,7 @@ export const trainerConfigs: TrainerConfigs = { p.generateName(); }), ) - .setInstantTera(3), // Tera Fairy Sylveon + .setInstantTera(4), // Tera Fairy Sylveon [TrainerType.PENNY_2]: new TrainerConfig(++t) .setName("Cassiopeia") .initForEvilTeamLeader("Star Boss", [], true) diff --git a/src/enums/battler-index.ts b/src/enums/battler-index.ts index 253e5bfc3ed..97c44f51c5c 100644 --- a/src/enums/battler-index.ts +++ b/src/enums/battler-index.ts @@ -1,5 +1,5 @@ /** - * The index of a given Pokemon on-field. + * The index of a given Pokemon on-field. \ * Used as an index into `globalScene.getField`, as well as for most target-specifying effects. */ export enum BattlerIndex { diff --git a/src/enums/challenge-type.ts b/src/enums/challenge-type.ts index 053bcf92011..f3a4b7c68f9 100644 --- a/src/enums/challenge-type.ts +++ b/src/enums/challenge-type.ts @@ -18,6 +18,11 @@ export enum ChallengeType { * @see {@link Challenge.applyStarterPointCost} */ STARTER_COST, + /** + * Challenges which modify the starter data in starter select + * @see {@link Challenge.applyStarterSelectModify} + */ + STARTER_SELECT_MODIFY, /** * Challenges which modify your starters in some way * @see {@link Challenge.applyStarterModify} diff --git a/src/enums/stat.ts b/src/enums/stat.ts index a2b81b7e64b..72ccc065850 100644 --- a/src/enums/stat.ts +++ b/src/enums/stat.ts @@ -64,7 +64,7 @@ export function getStatStageChangeDescriptionKey(stages: number, isIncrease: boo * @returns the translation key corresponding to the given {@linkcode Stat} */ export function getStatKey(stat: Stat) { - return `pokemonInfo:Stat.${Stat[stat]}`; + return `pokemonInfo:stat.${Stat[stat].toLowerCase()}`; } /** @@ -73,5 +73,5 @@ export function getStatKey(stat: Stat) { * @returns the translation key corresponding to the given {@linkcode Stat} */ export function getShortenedStatKey(stat: PermanentStat) { - return `pokemonInfo:Stat.${Stat[stat]}shortened`; + return `pokemonInfo:stat.${Stat[stat].toLowerCase()}Shortened`; } diff --git a/src/enums/status-effect.ts b/src/enums/status-effect.ts index b79951f530a..3064dbe907f 100644 --- a/src/enums/status-effect.ts +++ b/src/enums/status-effect.ts @@ -1,3 +1,5 @@ +/** Enum representing all non-volatile status effects. */ +// TODO: Remove StatusEffect.FAINT export enum StatusEffect { NONE, POISON, diff --git a/src/field/arena.ts b/src/field/arena.ts index 1b15cc3c761..7d7cf8ecce4 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -8,7 +8,7 @@ import Overrides from "#app/overrides"; import type { BiomeTierTrainerPools, PokemonPools } from "#balance/biomes"; import { BiomePoolTier, biomePokemonPools, biomeTrainerPools } from "#balance/biomes"; import type { ArenaTag } from "#data/arena-tag"; -import { ArenaTrapTag, getArenaTag } from "#data/arena-tag"; +import { EntryHazardTag, getArenaTag } from "#data/arena-tag"; import { SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "#data/form-change-triggers"; import type { PokemonSpecies } from "#data/pokemon-species"; import { PositionalTagManager } from "#data/positional-tags/positional-tag-manager"; @@ -709,8 +709,8 @@ export class Arena { if (existingTag) { existingTag.onOverlap(this, globalScene.getPokemonById(sourceId)); - if (existingTag instanceof ArenaTrapTag) { - const { tagType, side, turnCount, layers, maxLayers } = existingTag as ArenaTrapTag; + if (existingTag instanceof EntryHazardTag) { + const { tagType, side, turnCount, layers, maxLayers } = existingTag as EntryHazardTag; this.eventTarget.dispatchEvent(new TagAddedEvent(tagType, side, turnCount, layers, maxLayers)); } @@ -723,7 +723,7 @@ export class Arena { newTag.onAdd(this, quiet); this.tags.push(newTag); - const { layers = 0, maxLayers = 0 } = newTag instanceof ArenaTrapTag ? newTag : {}; + const { layers = 0, maxLayers = 0 } = newTag instanceof EntryHazardTag ? newTag : {}; this.eventTarget.dispatchEvent( new TagAddedEvent(newTag.tagType, newTag.side, newTag.turnCount, layers, maxLayers), @@ -942,7 +942,7 @@ export class Arena { case BiomeId.RUINS: return 0.0; case BiomeId.WASTELAND: - return 6.336; + return 6.024; case BiomeId.ABYSS: return 20.113; case BiomeId.SPACE: diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 3a5d435fb36..f29e8b204e8 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -237,6 +237,11 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { public ivs: number[]; public nature: Nature; public moveset: PokemonMove[]; + /** + * This Pokemon's current {@link https://m.bulbapedia.bulbagarden.net/wiki/Status_condition#Non-volatile_status | non-volatile status condition}, + * or `null` if none exist. + * @todo Make private + */ public status: Status | null; public friendship: number; public metLevel: number; @@ -1647,19 +1652,6 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { return precise ? this.hp / this.getMaxHp() : Math.round((this.hp / this.getMaxHp()) * 100) / 100; } - generateGender(): void { - if (this.species.malePercent === null) { - this.gender = Gender.GENDERLESS; - } else { - const genderChance = (this.id % 256) * 0.390625; - if (genderChance < this.species.malePercent) { - this.gender = Gender.MALE; - } else { - this.gender = Gender.FEMALE; - } - } - } - /** * Return this Pokemon's {@linkcode Gender}. * @param ignoreOverride - Whether to ignore any overrides caused by {@linkcode MoveId.TRANSFORM | Transform}; default `false` @@ -4746,7 +4738,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { * @param reason - The reason for the status application failure - * can be "overlap" (already has same status), "other" (generic fail message) * or a {@linkcode TerrainType} for terrain-based blockages. - * Defaults to "other". + * Default `"other"` */ queueStatusImmuneMessage( quiet: boolean, @@ -4775,15 +4767,20 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { } /** - * Checks if a status effect can be applied to the Pokemon. + * Check if a status effect can be applied to this {@linkcode Pokemon}. * - * @param effect The {@linkcode StatusEffect} whose applicability is being checked - * @param quiet Whether in-battle messages should trigger or not - * @param overrideStatus Whether the Pokemon's current status can be overriden - * @param sourcePokemon The Pokemon that is setting the status effect - * @param ignoreField Whether any field effects (weather, terrain, etc.) should be considered + * @param effect - The {@linkcode StatusEffect} whose applicability is being checked + * @param quiet - Whether to suppress in-battle messages for status checks; default `false` + * @param overrideStatus - Whether to allow overriding the Pokemon's current status with a different one; default `false` + * @param sourcePokemon - The {@linkcode Pokemon} applying the status effect to the target, + * or `null` if the status is applied from a non-Pokemon source (hazards, etc.); default `null` + * @param ignoreField - Whether to ignore field effects (weather, terrain, etc.) preventing status application; + * default `false` + * @returns Whether {@linkcode effect} can be applied to this Pokemon. */ - canSetStatus( + // TODO: Review and verify the message order precedence in mainline if multiple status-blocking effects are present at once + // TODO: Make argument order consistent with `trySetStatus` + public canSetStatus( effect: StatusEffect, quiet = false, overrideStatus = false, @@ -4791,6 +4788,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { ignoreField = false, ): boolean { if (effect !== StatusEffect.FAINT) { + // Status-overriding moves (i.e. Rest) fail if their respective status already exists; + // all other moves fail if the target already has _any_ status if (overrideStatus ? this.status?.effect === effect : this.status) { this.queueStatusImmuneMessage(quiet, overrideStatus ? "overlap" : "other"); // having different status displays generic fail message return false; @@ -4803,73 +4802,62 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { const types = this.getTypes(true, true); + /* Whether the target is immune to the specific status being applied. */ + let isImmune = false; + /** The reason for a potential blockage; default "other" for type-based. */ + let reason: "other" | Exclude = "other"; + switch (effect) { 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 => { - // Check if the Pokemon is not immune to Poison/Toxic + case StatusEffect.TOXIC: + // Check for type based immunities and/or Corrosion from the applier. + isImmune = types.some(defType => { + // only 1 immunity needed to block if (defType !== PokemonType.POISON && defType !== PokemonType.STEEL) { return false; } - // Check if the source Pokemon has an ability that cancels the Poison/Toxic immunity + // No source (such as from Toxic Spikes) = blocked by default + if (!sourcePokemon) { + return true; + } + const cancelImmunity = new BooleanHolder(false); // TODO: Determine if we need to pass `quiet` as the value for simulated in this call - if (sourcePokemon) { - applyAbAttrs("IgnoreTypeStatusEffectImmunityAbAttr", { - pokemon: sourcePokemon, - cancelled: cancelImmunity, - statusEffect: effect, - defenderType: defType, - }); - if (cancelImmunity.value) { - return false; - } - } - - return true; + applyAbAttrs("IgnoreTypeStatusEffectImmunityAbAttr", { + pokemon: sourcePokemon, + cancelled: cancelImmunity, + statusEffect: effect, + defenderType: defType, + }); + return !cancelImmunity.value; }); - - if (this.isOfType(PokemonType.POISON) || this.isOfType(PokemonType.STEEL)) { - if (poisonImmunity.includes(true)) { - this.queueStatusImmuneMessage(quiet); - return false; - } - } break; - } case StatusEffect.PARALYSIS: - if (this.isOfType(PokemonType.ELECTRIC)) { - this.queueStatusImmuneMessage(quiet); - return false; - } + isImmune = this.isOfType(PokemonType.ELECTRIC); break; case StatusEffect.SLEEP: - if (this.isGrounded() && globalScene.arena.terrain?.terrainType === TerrainType.ELECTRIC) { - this.queueStatusImmuneMessage(quiet, TerrainType.ELECTRIC); - return false; - } + isImmune = this.isGrounded() && globalScene.arena.getTerrainType() === TerrainType.ELECTRIC; + reason = TerrainType.ELECTRIC; break; - case StatusEffect.FREEZE: - if ( + case StatusEffect.FREEZE: { + const weatherType = globalScene.arena.getWeatherType(); + isImmune = this.isOfType(PokemonType.ICE) || - (!ignoreField && - globalScene?.arena?.weather?.weatherType && - [WeatherType.SUNNY, WeatherType.HARSH_SUN].includes(globalScene.arena.weather.weatherType)) - ) { - this.queueStatusImmuneMessage(quiet); - return false; - } + (!ignoreField && (weatherType === WeatherType.SUNNY || weatherType === WeatherType.HARSH_SUN)); break; + } case StatusEffect.BURN: - if (this.isOfType(PokemonType.FIRE)) { - this.queueStatusImmuneMessage(quiet); - return false; - } + isImmune = this.isOfType(PokemonType.FIRE); break; } + if (isImmune) { + this.queueStatusImmuneMessage(quiet, reason); + return false; + } + + // Check for cancellations from self/ally abilities const cancelled = new BooleanHolder(false); applyAbAttrs("StatusEffectImmunityAbAttr", { pokemon: this, effect, cancelled, simulated: quiet }); if (cancelled.value) { @@ -4886,14 +4874,11 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { source: sourcePokemon, }); if (cancelled.value) { - break; + return false; } } - if (cancelled.value) { - return false; - } - + // Perform safeguard checks if (sourcePokemon && sourcePokemon !== this && this.isSafeguarded(sourcePokemon)) { if (!quiet) { globalScene.phaseManager.queueMessage( @@ -4906,18 +4891,36 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { return true; } - trySetStatus( - effect?: StatusEffect, - asPhase = false, + /** + * Attempt to set this Pokemon's status to the specified condition. + * Enqueues a new `ObtainStatusEffectPhase` to trigger animations, etc. + * @param effect - The {@linkcode StatusEffect} to set + * @param sourcePokemon - The {@linkcode Pokemon} applying the status effect to the target, + * or `null` if the status is applied from a non-Pokemon source (hazards, etc.); default `null` + * @param sleepTurnsRemaining - The number of turns to set {@linkcode StatusEffect.SLEEP} for; + * defaults to a random number between 2 and 4 and is unused for non-Sleep statuses + * @param sourceText - The text to show for the source of the status effect, if any; default `null` + * @param overrideStatus - Whether to allow overriding the Pokemon's current status with a different one; default `false` + * @param quiet - Whether to suppress in-battle messages for status checks; default `true` + * @param overrideMessage - String containing text to be displayed upon status setting; defaults to normal key for status + * and is used exclusively for Rest + * @returns Whether the status effect phase was successfully created. + * @see {@linkcode doSetStatus} - alternate function that sets status immediately (albeit without condition checks). + */ + public trySetStatus( + effect: StatusEffect, sourcePokemon: Pokemon | null = null, - turnsRemaining = 0, + sleepTurnsRemaining?: number, sourceText: string | null = null, overrideStatus?: boolean, quiet = true, + overrideMessage?: string, ): boolean { + // TODO: This needs to propagate failure status for status moves if (!effect) { return false; } + if (!this.canSetStatus(effect, quiet, overrideStatus, sourcePokemon)) { return false; } @@ -4937,50 +4940,102 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { } } - if (asPhase) { - if (overrideStatus) { - this.resetStatus(false); - } - globalScene.phaseManager.unshiftNew( - "ObtainStatusEffectPhase", - this.getBattlerIndex(), - effect, - turnsRemaining, - sourceText, - sourcePokemon, - ); - return true; + if (overrideStatus) { + this.resetStatus(false); } - let sleepTurnsRemaining: NumberHolder; - - if (effect === StatusEffect.SLEEP) { - sleepTurnsRemaining = new NumberHolder(this.randBattleSeedIntRange(2, 4)); - - this.setFrameRate(4); - - // If the user is invulnerable, lets remove their invulnerability when they fall asleep - const invulnerableTags = [ - BattlerTagType.UNDERGROUND, - BattlerTagType.UNDERWATER, - BattlerTagType.HIDDEN, - BattlerTagType.FLYING, - ]; - - const tag = invulnerableTags.find(t => this.getTag(t)); - - if (tag) { - this.removeTag(tag); - this.getMoveQueue().pop(); - } - } - - sleepTurnsRemaining = sleepTurnsRemaining!; // tell TS compiler it's defined - this.status = new Status(effect, 0, sleepTurnsRemaining?.value); + globalScene.phaseManager.unshiftNew( + "ObtainStatusEffectPhase", + this.getBattlerIndex(), + effect, + sourcePokemon, + sleepTurnsRemaining, + sourceText, + overrideMessage, + ); return true; } + /** + * Set this Pokemon's {@linkcode status | non-volatile status condition} to the specified effect. + * @param effect - The {@linkcode StatusEffect} to set + * @remarks + * ⚠️ This method does **not** check for feasibility; that is the responsibility of the caller. + */ + doSetStatus(effect: Exclude): void; + /** + * Set this Pokemon's {@linkcode status | non-volatile status condition} to the specified effect. + * @param effect - {@linkcode StatusEffect.SLEEP} + * @param sleepTurnsRemaining - The number of turns to inflict sleep for; defaults to a random number between 2 and 4 + * @remarks + * ⚠️ This method does **not** check for feasibility; that is the responsibility of the caller. + */ + doSetStatus(effect: StatusEffect.SLEEP, sleepTurnsRemaining?: number): void; + /** + * Set this Pokemon's {@linkcode status | non-volatile status condition} to the specified effect. + * @param effect - The {@linkcode StatusEffect} to set + * @param sleepTurnsRemaining - The number of turns to inflict sleep for; defaults to a random number between 2 and 4 + * and is unused for all non-sleep Statuses + * @remarks + * ⚠️ This method does **not** check for feasibility; that is the responsibility of the caller. + */ + doSetStatus(effect: StatusEffect, sleepTurnsRemaining?: number): void; + /** + * Set this Pokemon's {@linkcode status | non-volatile status condition} to the specified effect. + * @param effect - The {@linkcode StatusEffect} to set + * @param sleepTurnsRemaining - The number of turns to inflict sleep for; defaults to a random number between 2 and 4 + * and is unused for all non-sleep Statuses + * @remarks + * ⚠️ This method does **not** check for feasibility; that is the responsibility of the caller. + * @todo Make this and all related fields private and change tests to use a field-based helper or similar + */ + doSetStatus( + effect: StatusEffect, + sleepTurnsRemaining = effect !== StatusEffect.SLEEP ? 0 : this.randBattleSeedIntRange(2, 4), + ): void { + switch (effect) { + case StatusEffect.POISON: + case StatusEffect.TOXIC: + this.setFrameRate(8); + break; + case StatusEffect.PARALYSIS: + this.setFrameRate(5); + break; + case StatusEffect.SLEEP: { + this.setFrameRate(3); + + // If the user is semi-invulnerable when put asleep (such as due to Yawm), + // remove their invulnerability and cancel the upcoming move from the queue + const invulnTagTypes = [ + BattlerTagType.FLYING, + BattlerTagType.UNDERGROUND, + BattlerTagType.UNDERWATER, + BattlerTagType.HIDDEN, + ]; + + if (this.findTag(t => invulnTagTypes.includes(t.tagType))) { + this.findAndRemoveTags(t => invulnTagTypes.includes(t.tagType)); + this.getMoveQueue().shift(); + } + break; + } + case StatusEffect.FREEZE: + this.setFrameRate(0); + break; + case StatusEffect.BURN: + this.setFrameRate(14); + break; + case StatusEffect.FAINT: + break; + default: + effect satisfies StatusEffect.NONE; + break; + } + + this.status = new Status(effect, 0, sleepTurnsRemaining); + } + /** * Resets the status of a pokemon. * @param revive Whether revive should be cured; defaults to true. @@ -5009,8 +5064,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { public clearStatus(confusion: boolean, reloadAssets: boolean) { const lastStatus = this.status?.effect; this.status = null; + this.setFrameRate(10); if (lastStatus === StatusEffect.SLEEP) { - this.setFrameRate(10); if (this.getTag(BattlerTagType.NIGHTMARE)) { this.lapseTag(BattlerTagType.NIGHTMARE); } @@ -5708,7 +5763,11 @@ export class PlayerPokemon extends Pokemon { } if (!dataSource) { - if (globalScene.gameMode.isDaily) { + if ( + globalScene.gameMode.isDaily || + // Keldeo is excluded due to crashes involving its signature move and the associated form change + (Overrides.STARTER_SPECIES_OVERRIDE && Overrides.STARTER_SPECIES_OVERRIDE !== SpeciesId.KELDEO) + ) { this.generateAndPopulateMoveset(); } else { this.moveset = []; diff --git a/src/field/trainer.ts b/src/field/trainer.ts index 584c9310932..acbc8031dbc 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -1,7 +1,7 @@ import { globalScene } from "#app/global-scene"; import { pokemonPrevolutions } from "#balance/pokemon-evolutions"; import { signatureSpecies } from "#balance/signature-species"; -import { ArenaTrapTag } from "#data/arena-tag"; +import { EntryHazardTag } from "#data/arena-tag"; import type { PokemonSpecies } from "#data/pokemon-species"; import { ArenaTagSide } from "#enums/arena-tag-side"; import { PartyMemberStrength } from "#enums/party-member-strength"; @@ -16,14 +16,11 @@ import type { PersistentModifier } from "#modifiers/modifier"; import { getIsInitialized, initI18n } from "#plugins/i18n"; import type { TrainerConfig } from "#trainers/trainer-config"; import { trainerConfigs } from "#trainers/trainer-config"; -import { - TrainerPartyCompoundTemplate, - type TrainerPartyTemplate, - trainerPartyTemplates, -} from "#trainers/trainer-party-template"; +import { TrainerPartyCompoundTemplate, type TrainerPartyTemplate } from "#trainers/trainer-party-template"; import { randSeedInt, randSeedItem, randSeedWeightedItem } from "#utils/common"; +import { getRandomLocaleEntry } from "#utils/i18n"; import { getPokemonSpecies } from "#utils/pokemon-utils"; -import { toSnakeCase } from "#utils/strings"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; export class Trainer extends Phaser.GameObjects.Container { @@ -35,6 +32,18 @@ export class Trainer extends Phaser.GameObjects.Container { public partnerNameKey: string | undefined; public originalIndexes: { [key: number]: number } = {}; + /** + * Create a new Trainer. + * @param trainerType - The {@linkcode TrainerType} for this trainer, used to determine + * name, sprite, party contents and other details. + * @param variant - The {@linkcode TrainerVariant} for this trainer (if any are available) + * @param partyTemplateIndex - If provided, will override the trainer's party template with the given + * version. + * @param nameKey - If provided, will override the name key of the trainer + * @param partnerNameKey - If provided, will override the + * @param trainerConfigOverride - If provided, will override the trainer config for the given trainer type + * @todo Review how many of these parameters we actually need + */ constructor( trainerType: TrainerType, variant: TrainerVariant, @@ -44,13 +53,11 @@ export class Trainer extends Phaser.GameObjects.Container { trainerConfigOverride?: TrainerConfig, ) { super(globalScene, -72, 80); - this.config = trainerConfigs.hasOwnProperty(trainerType) - ? trainerConfigs[trainerType] - : trainerConfigs[TrainerType.ACE_TRAINER]; - - if (trainerConfigOverride) { - this.config = trainerConfigOverride; - } + this.config = + trainerConfigOverride ?? + (trainerConfigs.hasOwnProperty(trainerType) + ? trainerConfigs[trainerType] + : trainerConfigs[TrainerType.ACE_TRAINER]); this.variant = variant; this.partyTemplateIndex = Math.min( @@ -59,20 +66,21 @@ export class Trainer extends Phaser.GameObjects.Container { : randSeedWeightedItem(this.config.partyTemplates.map((_, i) => i)), this.config.partyTemplates.length - 1, ); - const classKey = `trainersCommon:${TrainerType[trainerType]}`; + // TODO: Rework this and add actual error handling for missing names + const classKey = `trainersCommon:${toCamelCase(TrainerType[trainerType])}`; if (i18next.exists(classKey, { returnObjects: true })) { if (nameKey) { this.nameKey = nameKey; + this.name = i18next.t(nameKey); } else { - const genderKey = i18next.exists(`${classKey}.MALE`) + const genderKey = i18next.exists(`${classKey}.male`) ? variant === TrainerVariant.FEMALE - ? ".FEMALE" - : ".MALE" + ? ".female" + : ".male" : ""; - const trainerKey = randSeedItem(Object.keys(i18next.t(`${classKey}${genderKey}`, { returnObjects: true }))); - this.nameKey = `${classKey}${genderKey}.${trainerKey}`; + [this.nameKey, this.name] = getRandomLocaleEntry(`${classKey}${genderKey}`); } - this.name = i18next.t(this.nameKey); + if (variant === TrainerVariant.DOUBLE) { if (this.config.doubleOnly) { if (partnerNameKey) { @@ -82,16 +90,8 @@ export class Trainer extends Phaser.GameObjects.Container { [this.name, this.partnerName] = this.name.split(" & "); } } else { - const partnerGenderKey = i18next.exists(`${classKey}.FEMALE`) ? ".FEMALE" : ""; - const partnerTrainerKey = randSeedItem( - Object.keys( - i18next.t(`${classKey}${partnerGenderKey}`, { - returnObjects: true, - }), - ), - ); - this.partnerNameKey = `${classKey}${partnerGenderKey}.${partnerTrainerKey}`; - this.partnerName = i18next.t(this.partnerNameKey); + const partnerGenderKey = i18next.exists(`${classKey}.female`) ? ".female" : ""; + [this.partnerNameKey, this.partnerName] = getRandomLocaleEntry(`${classKey}${partnerGenderKey}`); } } } @@ -109,10 +109,6 @@ export class Trainer extends Phaser.GameObjects.Container { break; } - console.log( - Object.keys(trainerPartyTemplates)[Object.values(trainerPartyTemplates).indexOf(this.getPartyTemplate())], - ); - const getSprite = (hasShadow?: boolean, forceFemale?: boolean) => { const ret = globalScene.addFieldSprite( 0, @@ -157,9 +153,9 @@ export class Trainer extends Phaser.GameObjects.Container { /** * Returns the name of the trainer based on the provided trainer slot and the option to include a title. - * @param {TrainerSlot} trainerSlot - The slot to determine which name to use. Defaults to TrainerSlot.NONE. - * @param {boolean} includeTitle - Whether to include the title in the returned name. Defaults to false. - * @returns {string} - The formatted name of the trainer. + * @param trainerSlot - The slot to determine which name to use; default `TrainerSlot.NONE` + * @param includeTitle - Whether to include the title in the returned name; default `false` + * @returns - The formatted name of the trainer */ getName(trainerSlot: TrainerSlot = TrainerSlot.NONE, includeTitle = false): string { // Get the base title based on the trainer slot and variant. @@ -170,7 +166,7 @@ export class Trainer extends Phaser.GameObjects.Container { 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:${toSnakeCase(name)}`); + title = i18next.t(`trainerClasses:${toCamelCase(name)}`); console.log("Localized grunt name: " + title); // Since grunts are not named we can just return the title return title; @@ -187,7 +183,7 @@ export class Trainer extends Phaser.GameObjects.Container { } // Get the localized trainer class name from the i18n file and set it as the title. // This is used for trainer class names, not titles like "Elite Four, Champion, etc." - title = i18next.t(`trainerClasses:${toSnakeCase(name)}`); + title = i18next.t(`trainerClasses:${toCamelCase(name)}`); } // If no specific trainer slot is set. @@ -208,7 +204,7 @@ export class Trainer extends Phaser.GameObjects.Container { if (this.config.titleDouble && this.variant === TrainerVariant.DOUBLE && !this.config.doubleOnly) { title = this.config.titleDouble; - name = i18next.t(`trainerNames:${toSnakeCase(this.config.nameDouble)}`); + name = i18next.t(`trainerNames:${toCamelCase(this.config.nameDouble)}`); } console.log(title ? `${title} ${name}` : name); @@ -584,8 +580,8 @@ export class Trainer extends Phaser.GameObjects.Container { score /= playerField.length; if (forSwitch && !p.isOnField()) { globalScene.arena - .findTagsOnSide(t => t instanceof ArenaTrapTag, ArenaTagSide.ENEMY) - .map(t => (score *= (t as ArenaTrapTag).getMatchupScoreMultiplier(p))); + .findTagsOnSide(t => t instanceof EntryHazardTag, ArenaTagSide.ENEMY) + .map(t => (score *= (t as EntryHazardTag).getMatchupScoreMultiplier(p))); } } diff --git a/src/game-mode.ts b/src/game-mode.ts index b44e786b3d9..513a2baaf95 100644 --- a/src/game-mode.ts +++ b/src/game-mode.ts @@ -82,6 +82,14 @@ export class GameMode implements GameModeConfig { return this.challenges.some(c => c.id === challenge && c.value !== 0); } + /** + * Helper function to see if a GameMode has any challenges, needed in tests + * @returns true if the game mode has at least one challenge + */ + hasAnyChallenges(): boolean { + return this.challenges.length > 0; + } + /** * Helper function to see if the game mode is using fresh start * @returns true if a fresh start challenge is being applied @@ -90,6 +98,19 @@ export class GameMode implements GameModeConfig { return this.hasChallenge(Challenges.FRESH_START); } + /** + * Helper function to see if the game mode is using fresh start + * @returns true if a fresh start challenge is being applied + */ + isFullFreshStartChallenge(): boolean { + for (const challenge of this.challenges) { + if (challenge.id === Challenges.FRESH_START && challenge.value === 1) { + return true; + } + } + return false; + } + /** * Helper function to get starting level for game mode. * @returns either: diff --git a/src/loading-scene.ts b/src/loading-scene.ts index bf4d87a99f3..0a42fc3fa7d 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -99,7 +99,7 @@ export class LoadingScene extends SceneBase { this.loadImage("type_tera", "ui"); this.loadAtlas("type_bgs", "ui"); this.loadAtlas("button_tera", "ui"); - this.loadImage("mystery_egg", "ui"); + this.loadImage("common_egg", "ui"); this.loadImage("normal_memory", "ui"); this.loadImage("dawn_icon_fg", "ui"); diff --git a/src/modifier/init-modifier-pools.ts b/src/modifier/init-modifier-pools.ts index 316d4dae741..3e180846183 100644 --- a/src/modifier/init-modifier-pools.ts +++ b/src/modifier/init-modifier-pools.ts @@ -279,7 +279,7 @@ function initGreatModifierPool() { new WeightedModifierType(modifierTypes.DIRE_HIT, 4), new WeightedModifierType(modifierTypes.SUPER_LURE, lureWeightFunc(15, 4)), new WeightedModifierType(modifierTypes.NUGGET, skipInLastClassicWaveOrDefault(5)), - new WeightedModifierType(modifierTypes.SPECIES_STAT_BOOSTER, 4), + new WeightedModifierType(modifierTypes.SPECIES_STAT_BOOSTER, 2), new WeightedModifierType( modifierTypes.EVOLUTION_ITEM, () => { diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index aca49313ff5..8b77900cb62 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -130,6 +130,7 @@ import { } from "#utils/common"; import { getEnumKeys, getEnumValues } from "#utils/enums"; import { getModifierPoolForType, getModifierType } from "#utils/modifier-utils"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; const outputModifierData = false; @@ -451,13 +452,13 @@ export class TerastallizeModifierType extends PokemonModifierType { get name(): string { return i18next.t("modifierType:ModifierType.TerastallizeModifierType.name", { - teraType: i18next.t(`pokemonInfo:Type.${PokemonType[this.teraType]}`), + teraType: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[this.teraType])}`), }); } getDescription(): string { return i18next.t("modifierType:ModifierType.TerastallizeModifierType.description", { - teraType: i18next.t(`pokemonInfo:Type.${PokemonType[this.teraType]}`), + teraType: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[this.teraType])}`), }); } @@ -861,7 +862,7 @@ export class AttackTypeBoosterModifierType getDescription(): string { // TODO: Need getTypeName? return i18next.t("modifierType:ModifierType.AttackTypeBoosterModifierType.description", { - moveType: i18next.t(`pokemonInfo:Type.${PokemonType[this.moveType]}`), + moveType: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[this.moveType])}`), }); } diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 076e2656b5c..7d0478628b4 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1733,12 +1733,12 @@ export class TurnStatusEffectModifier extends PokemonHeldItemModifier { } /** - * Tries to inflicts the holder with the associated {@linkcode StatusEffect}. - * @param pokemon {@linkcode Pokemon} that holds the held item + * Attempt to inflict the holder with the associated {@linkcode StatusEffect}. + * @param pokemon - The {@linkcode Pokemon} holding the item * @returns `true` if the status effect was applied successfully */ override apply(pokemon: Pokemon): boolean { - return pokemon.trySetStatus(this.effect, true, undefined, undefined, this.type.name); + return pokemon.trySetStatus(this.effect, pokemon, undefined, this.type.name); } getMaxHeldItemCount(_pokemon: Pokemon): number { @@ -3605,7 +3605,7 @@ export class EnemyAttackStatusEffectChanceModifier extends EnemyPersistentModifi */ override apply(enemyPokemon: Pokemon): boolean { if (randSeedFloat() <= this.chance * this.getStackCount()) { - return enemyPokemon.trySetStatus(this.effect, true); + return enemyPokemon.trySetStatus(this.effect); } return false; diff --git a/src/overrides.ts b/src/overrides.ts index 48d7428cad9..b8212ea8fd6 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -78,15 +78,19 @@ class DefaultOverrides { readonly ARENA_TINT_OVERRIDE: TimeOfDay | null = null; /** Multiplies XP gained by this value including 0. Set to null to ignore the override. */ readonly XP_MULTIPLIER_OVERRIDE: number | null = null; - /** Sets the level cap to this number during experience gain calculations. Set to `0` to disable override & use normal wave-based level caps, - or any negative number to set it to 9 quadrillion (effectively disabling it). */ + /** + * Sets the level cap to this number during experience gain calculations. + * + * Set to `0` to disable override & use normal wave-based level caps, + * or any negative number to disable level caps entirely. + */ readonly LEVEL_CAP_OVERRIDE: number = 0; /** * If defined, overrides random critical hit rolls to always or never succeed. * Ignored if the move is guaranteed to always/never crit. */ readonly CRITICAL_HIT_OVERRIDE: boolean | null = null; - /** default 1000 */ + /** @defaultValue `1000` */ readonly STARTING_MONEY_OVERRIDE: number = 0; /** Sets all shop item prices to 0 */ readonly WAIVE_SHOP_FEES_OVERRIDE: boolean = false; @@ -130,8 +134,8 @@ class DefaultOverrides { // PLAYER OVERRIDES // ---------------- /** - * Set the form index of any starter in the party whose `speciesId` is inside this override - * @see {@link allSpecies} in `src/data/pokemon-species.ts` for form indexes + * Set the form index of any starter in the party whose {@linkcode SpeciesId} is inside this override + * @see `src/data/pokemon-species.ts` for form indexes * @example * ``` * const STARTER_FORM_OVERRIDES = { @@ -141,23 +145,14 @@ class DefaultOverrides { */ readonly STARTER_FORM_OVERRIDES: Partial> = {}; - /** default 5 or 20 for Daily */ + /** @defaultValue `20` for Daily and `5` for all other modes */ readonly STARTING_LEVEL_OVERRIDE: number = 0; - /** - * SPECIES OVERRIDE - * will only apply to the first starter in your party or each enemy pokemon - * default is 0 to not override - * @example SPECIES_OVERRIDE = SpeciesId.Bulbasaur; - */ - readonly STARTER_SPECIES_OVERRIDE: SpeciesId | number = 0; - /** - * This will force your starter to be a random fusion - */ + /** Will override the species of your pokemon when starting a new run */ + readonly STARTER_SPECIES_OVERRIDE: SpeciesId | 0 = 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: SpeciesId | number = 0; + /** This will override the species of the fusion */ + readonly STARTER_FUSION_SPECIES_OVERRIDE: SpeciesId | 0 = 0; readonly ABILITY_OVERRIDE: AbilityId = AbilityId.NONE; readonly PASSIVE_ABILITY_OVERRIDE: AbilityId = AbilityId.NONE; readonly HAS_PASSIVE_ABILITY_OVERRIDE: boolean | null = null; @@ -180,13 +175,9 @@ class DefaultOverrides { // OPPONENT / ENEMY OVERRIDES // -------------------------- readonly ENEMY_SPECIES_OVERRIDE: SpeciesId | number = 0; - /** - * This will make all opponents fused Pokemon - */ + /** This will make all enemies fused Pokemon */ readonly ENEMY_FUSION_OVERRIDE: boolean = false; - /** - * This will override the species of the fusion only when the opponent is already a fusion - */ + /** This will override the species of the fusion only when the enemy is already a fusion */ readonly ENEMY_FUSION_SPECIES_OVERRIDE: SpeciesId | number = 0; readonly ENEMY_LEVEL_OVERRIDE: number = 0; readonly ENEMY_ABILITY_OVERRIDE: AbilityId = AbilityId.NONE; @@ -197,6 +188,7 @@ class DefaultOverrides { readonly ENEMY_MOVESET_OVERRIDE: MoveId | Array = []; readonly ENEMY_SHINY_OVERRIDE: boolean | null = null; readonly ENEMY_VARIANT_OVERRIDE: Variant | null = null; + /** * Overrides the IVs of enemy pokemon. Values must never be outside the range `0` to `31`! * - If set to a number between `0` and `31`, set all IVs of all enemy pokemon to that number. @@ -210,9 +202,9 @@ class DefaultOverrides { /** * Override to give the enemy Pokemon a given amount of health segments * - * 0 (default): the health segments will be handled normally based on wave, level and species - * 1: the Pokemon will have a single health segment and therefore will not be a boss - * 2+: the Pokemon will be a boss with the given number of health segments + * - `0` (default): the health segments will be handled normally based on wave, level and species + * - `1`: the Pokemon will have a single health segment and therefore will not be a boss + * - `2+`: the Pokemon will be a boss with the given number of health segments */ readonly ENEMY_HEALTH_SEGMENTS_OVERRIDE: number = 0; @@ -293,9 +285,7 @@ class DefaultOverrides { */ readonly ITEM_REWARD_OVERRIDE: ModifierOverride[] = []; - /** - * If `true`, disable all non-scripted opponent trainer encounters. - */ + /** If `true`, disable all non-scripted opponent trainer encounters. */ readonly DISABLE_STANDARD_TRAINERS_OVERRIDE: boolean = false; /** diff --git a/src/phase.ts b/src/phase.ts index eccbf3127e6..6fea6e3b0f0 100644 --- a/src/phase.ts +++ b/src/phase.ts @@ -2,8 +2,10 @@ import { globalScene } from "#app/global-scene"; import type { PhaseMap, PhaseString } from "#types/phase-types"; export abstract class Phase { + /** Start the current phase. */ start() {} + /** End the current phase and start a new one. */ end() { globalScene.phaseManager.shiftPhase(); } diff --git a/src/phases/attempt-capture-phase.ts b/src/phases/attempt-capture-phase.ts index b34ddb0c59a..699caa2af21 100644 --- a/src/phases/attempt-capture-phase.ts +++ b/src/phases/attempt-capture-phase.ts @@ -271,7 +271,7 @@ export class AttemptCapturePhase extends PokemonPhase { const removePokemon = () => { globalScene.addFaintedEnemyScore(pokemon); pokemon.hp = 0; - pokemon.trySetStatus(StatusEffect.FAINT); + pokemon.doSetStatus(StatusEffect.FAINT); globalScene.clearEnemyHeldItemModifiers(); pokemon.leaveField(true, true, true); }; diff --git a/src/phases/attempt-run-phase.ts b/src/phases/attempt-run-phase.ts index a59667bdd4e..e8212a27243 100644 --- a/src/phases/attempt-run-phase.ts +++ b/src/phases/attempt-run-phase.ts @@ -45,7 +45,7 @@ export class AttemptRunPhase extends FieldPhase { enemyField.forEach(enemyPokemon => { enemyPokemon.hideInfo().then(() => enemyPokemon.destroy()); enemyPokemon.hp = 0; - enemyPokemon.trySetStatus(StatusEffect.FAINT); + enemyPokemon.doSetStatus(StatusEffect.FAINT); }); globalScene.phaseManager.pushNew("BattleEndPhase", false); diff --git a/src/phases/command-phase.ts b/src/phases/command-phase.ts index ff9ee7cc197..6ca0679af4d 100644 --- a/src/phases/command-phase.ts +++ b/src/phases/command-phase.ts @@ -20,6 +20,7 @@ import { UiMode } from "#enums/ui-mode"; import type { PlayerPokemon } from "#field/pokemon"; import type { MoveTargetSet } from "#moves/move"; import { getMoveTargets } from "#moves/move-utils"; +import type { PokemonMove } from "#moves/pokemon-move"; import { FieldPhase } from "#phases/field-phase"; import type { TurnMove } from "#types/turn-move"; import { applyChallenges } from "#utils/challenge-utils"; @@ -207,10 +208,9 @@ export class CommandPhase extends FieldPhase { * Submethod of {@linkcode handleFightCommand} responsible for queuing the appropriate * error message when a move cannot be used. * @param user - The pokemon using the move - * @param cursor - The index of the move in the moveset + * @param move - The move that cannot be used */ - private queueFightErrorMessage(user: PlayerPokemon, cursor: number) { - const move = user.getMoveset()[cursor]; + private queueFightErrorMessage(user: PlayerPokemon, move: PokemonMove) { globalScene.ui.setMode(UiMode.MESSAGE); // Set the translation key for why the move cannot be selected @@ -277,15 +277,19 @@ export class CommandPhase extends FieldPhase { let canUse = cursor === -1 || playerPokemon.trySelectMove(cursor, ignorePP); + const moveset = playerPokemon.getMoveset(); + // Ternary here ensures we don't compute struggle conditions unless necessary - const useStruggle = canUse - ? false - : cursor > -1 && !playerPokemon.getMoveset().some(m => m.isUsable(playerPokemon)); + const useStruggle = canUse ? false : cursor > -1 && !moveset.some(m => m.isUsable(playerPokemon)); canUse ||= useStruggle; if (!canUse) { - this.queueFightErrorMessage(playerPokemon, cursor); + // Selected move *may* be undefined if the cursor is over a position that the mon does not have + const selectedMove: PokemonMove | undefined = moveset[cursor]; + if (selectedMove) { + this.queueFightErrorMessage(playerPokemon, moveset[cursor]); + } return false; } @@ -376,7 +380,6 @@ export class CommandPhase extends FieldPhase { * - It is a trainer battle * - The player is in the {@linkcode BiomeId.END | End} biome and * - it is not classic mode; or - * - the fresh start challenge is active; or * - the player has not caught the target before and the player is still missing more than one starter * - The player is in a mystery encounter that disallows catching the pokemon * @returns Whether a pokeball can be thrown @@ -385,19 +388,37 @@ export class CommandPhase extends FieldPhase { const { arena, currentBattle, gameData, gameMode } = globalScene; const { battleType } = currentBattle; const { biomeType } = arena; - const { isClassic } = gameMode; + const { isClassic, isEndless, isDaily } = gameMode; const { dexData } = gameData; + const isClassicFinalBoss = gameMode.isBattleClassicFinalBoss(globalScene.currentBattle.waveIndex); + const isEndlessMinorBoss = gameMode.isEndlessMinorBoss(globalScene.currentBattle.waveIndex); + const isFullFreshStart = gameMode.isFullFreshStartChallenge(); const someUncaughtSpeciesOnField = globalScene .getEnemyField() .some(p => p.isActive() && !dexData[p.species.speciesId].caughtAttr); const missingMultipleStarters = gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarterCosts).length - 1; - if ( - biomeType === BiomeId.END && - (!isClassic || gameMode.isFreshStartChallenge() || (someUncaughtSpeciesOnField && missingMultipleStarters)) - ) { - this.queueShowText("battle:noPokeballForce"); + + if (biomeType === BiomeId.END && battleType === BattleType.WILD) { + if ( + (isClassic && !isClassicFinalBoss && someUncaughtSpeciesOnField) || + (isFullFreshStart && !isClassicFinalBoss) || + (isEndless && !isEndlessMinorBoss) + ) { + // Uncatchable paradox mons in classic and endless + this.queueShowText("battle:noPokeballForce"); + } else if ( + (isClassic && isClassicFinalBoss && missingMultipleStarters) || + (isFullFreshStart && isClassicFinalBoss) || + (isEndless && isEndlessMinorBoss) || + isDaily + ) { + // Uncatchable final boss in classic, endless and daily + this.queueShowText("battle:noPokeballForceFinalBoss"); + } else { + return true; + } } else if (battleType === BattleType.TRAINER) { this.queueShowText("battle:noPokeballTrainer"); } else if (currentBattle.isBattleMysteryEncounter() && !currentBattle.mysteryEncounter!.catchAllowed) { @@ -420,14 +441,18 @@ export class CommandPhase extends FieldPhase { .getEnemyField() .filter(p => p.isActive(true)) .map(p => p.getBattlerIndex()); + + if (!this.checkCanUseBall()) { + return false; + } + if (targets.length > 1) { this.queueShowText("battle:noPokeballMulti"); return false; } - if (!this.checkCanUseBall()) { - return false; - } + const isChallengeActive = globalScene.gameMode.hasAnyChallenges(); + const isFinalBoss = globalScene.gameMode.isBattleClassicFinalBoss(globalScene.currentBattle.waveIndex); const numBallTypes = 5; if (cursor < numBallTypes) { @@ -436,11 +461,22 @@ export class CommandPhase extends FieldPhase { targetPokemon?.isBoss() && targetPokemon?.bossSegmentIndex >= 1 && // TODO: Decouple this hardcoded exception for wonder guard and just check the target... - !targetPokemon?.hasAbility(AbilityId.WONDER_GUARD, false, true) && - cursor < PokeballType.MASTER_BALL + !targetPokemon?.hasAbility(AbilityId.WONDER_GUARD, false, true) ) { - this.queueShowText("battle:noPokeballStrong"); - return false; + // When facing the final boss, it must be weakened unless a Master Ball is used AND no challenges are active. + // The message is customized for the final boss. + if ( + isFinalBoss && + (cursor < PokeballType.MASTER_BALL || (cursor === PokeballType.MASTER_BALL && isChallengeActive)) + ) { + this.queueShowText("battle:noPokeballForceFinalBossCatchable"); + return false; + } + // When facing any other boss, Master Ball can always be used, and we use the standard message. + if (cursor < PokeballType.MASTER_BALL) { + this.queueShowText("battle:noPokeballStrong"); + return false; + } } globalScene.currentBattle.turnCommands[this.fieldIndex] = { @@ -474,20 +510,21 @@ export class CommandPhase extends FieldPhase { } if (trappedAbMessages.length > 0) { if (isSwitch) { - globalScene.ui.setMode(UiMode.MESSAGE); + globalScene.ui.setMode(UiMode.MESSAGE).then(() => { + globalScene.ui.showText( + trappedAbMessages[0], + null, + () => { + globalScene.ui.showText("", 0); + if (isSwitch) { + globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex); + } + }, + null, + true, + ); + }); } - globalScene.ui.showText( - trappedAbMessages[0], - null, - () => { - globalScene.ui.showText("", 0); - if (isSwitch) { - globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex); - } - }, - null, - true, - ); } else { const trapTag = playerPokemon.getTag(TrappedTag); const fairyLockTag = globalScene.arena.getTagOnSide(ArenaTagType.FAIRY_LOCK, ArenaTagSide.PLAYER); diff --git a/src/phases/faint-phase.ts b/src/phases/faint-phase.ts index d1bd0ed0804..2d953043866 100644 --- a/src/phases/faint-phase.ts +++ b/src/phases/faint-phase.ts @@ -205,7 +205,7 @@ export class FaintPhase extends PokemonPhase { pokemon.lapseTags(BattlerTagLapseType.FAINT); pokemon.y -= 150; - pokemon.trySetStatus(StatusEffect.FAINT); + pokemon.doSetStatus(StatusEffect.FAINT); if (pokemon.isPlayer()) { globalScene.currentBattle.removeFaintedParticipant(pokemon as PlayerPokemon); } else { diff --git a/src/phases/game-over-phase.ts b/src/phases/game-over-phase.ts index 25dfffaa582..89162e591fc 100644 --- a/src/phases/game-over-phase.ts +++ b/src/phases/game-over-phase.ts @@ -65,8 +65,8 @@ export class GameOverPhase extends BattlePhase { const genderIndex = globalScene.gameData.gender ?? PlayerGender.UNSET; const genderStr = PlayerGender[genderIndex].toLowerCase(); globalScene.ui.showDialogue( - i18next.t("miscDialogue:ending_endless", { context: genderStr }), - i18next.t("miscDialogue:ending_name"), + i18next.t("miscDialogue:endingEndless", { context: genderStr }), + i18next.t("miscDialogue:endingName"), 0, () => this.handleGameOver(), ); @@ -119,19 +119,25 @@ export class GameOverPhase extends BattlePhase { * game mode and challenges. */ private awardRibbons(): void { - let ribbonFlags = 0; - if (globalScene.gameMode.isClassic) { - ribbonFlags |= RibbonData.CLASSIC; - } - if (isNuzlockeChallenge()) { - ribbonFlags |= RibbonData.NUZLOCKE; - } + let ribbonFlags = 0n; for (const challenge of globalScene.gameMode.challenges) { const ribbon = challenge.ribbonAwarded; if (challenge.value && ribbon) { ribbonFlags |= ribbon; } } + // Block other ribbons if flip stats or inverse is active + const flip_or_inverse = ribbonFlags & (RibbonData.FLIP_STATS | RibbonData.INVERSE); + if (flip_or_inverse) { + ribbonFlags = flip_or_inverse; + } else { + if (globalScene.gameMode.isClassic) { + ribbonFlags |= RibbonData.CLASSIC; + } + if (isNuzlockeChallenge()) { + ribbonFlags |= RibbonData.NUZLOCKE; + } + } // Award ribbons to all Pokémon in the player's party that are considered valid // for the current game mode and challenges. for (const pokemon of globalScene.getPlayerParty()) { @@ -167,6 +173,7 @@ export class GameOverPhase extends BattlePhase { this.awardRibbons(); } else if (globalScene.gameMode.isDaily && newClear) { globalScene.gameData.gameStats.dailyRunSessionsWon++; + globalScene.validateAchv(achvs.DAILY_VICTORY); } } diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index f88f9d0cad1..9a8e509e302 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -269,8 +269,8 @@ export class MovePhase extends BattlePhase { globalScene.phaseManager.queueMessage( getStatusEffectHealText(this.pokemon.status.effect, getPokemonNameWithAffix(this.pokemon)), ); - this.pokemon.resetStatus(); - this.pokemon.updateInfo(); + // cannot use `asPhase=true` as it will cause status to be reset _after_ move condition checks fire + this.pokemon.resetStatus(false, false, false, false); } } diff --git a/src/phases/obtain-status-effect-phase.ts b/src/phases/obtain-status-effect-phase.ts index fbadbed205b..4846130cf4d 100644 --- a/src/phases/obtain-status-effect-phase.ts +++ b/src/phases/obtain-status-effect-phase.ts @@ -3,71 +3,64 @@ import { globalScene } from "#app/global-scene"; import { getPokemonNameWithAffix } from "#app/messages"; import { CommonBattleAnim } from "#data/battle-anims"; import { SpeciesFormChangeStatusEffectTrigger } from "#data/form-change-triggers"; -import { getStatusEffectObtainText, getStatusEffectOverlapText } from "#data/status-effect"; +import { getStatusEffectObtainText } from "#data/status-effect"; import type { BattlerIndex } from "#enums/battler-index"; import { CommonAnim } from "#enums/move-anims-common"; import { StatusEffect } from "#enums/status-effect"; import type { Pokemon } from "#field/pokemon"; import { PokemonPhase } from "#phases/pokemon-phase"; -import { isNullOrUndefined } from "#utils/common"; export class ObtainStatusEffectPhase extends PokemonPhase { public readonly phaseName = "ObtainStatusEffectPhase"; - private statusEffect?: StatusEffect; - private turnsRemaining?: number; - private sourceText?: string | null; - private sourcePokemon?: Pokemon | null; + /** + * @param battlerIndex - The {@linkcode BattlerIndex} of the Pokemon obtaining the status effect. + * @param statusEffect - The {@linkcode StatusEffect} being applied. + * @param sourcePokemon - The {@linkcode Pokemon} applying the status effect to the target, + * or `null` if the status is applied from a non-Pokemon source (hazards, etc.); default `null`. + * @param sleepTurnsRemaining - The number of turns to set {@linkcode StatusEffect.SLEEP} for; + * defaults to a random number between 2 and 4 and is unused for non-Sleep statuses. + * @param sourceText - The text to show for the source of the status effect, if any; default `null`. + * @param statusMessage - A string containing text to be displayed upon status setting; + * defaults to normal key for status if empty or omitted. + */ constructor( battlerIndex: BattlerIndex, - statusEffect?: StatusEffect, - turnsRemaining?: number, - sourceText?: string | null, - sourcePokemon?: Pokemon | null, + private statusEffect: StatusEffect, + private sourcePokemon: Pokemon | null = null, + private sleepTurnsRemaining?: number, + sourceText: string | null = null, // TODO: This should take `undefined` instead of `null` + private statusMessage = "", ) { super(battlerIndex); - this.statusEffect = statusEffect; - this.turnsRemaining = turnsRemaining; - this.sourceText = sourceText; - this.sourcePokemon = sourcePokemon; + this.statusMessage ||= getStatusEffectObtainText( + statusEffect, + getPokemonNameWithAffix(this.getPokemon()), + sourceText ?? undefined, + ); } start() { const pokemon = this.getPokemon(); - if (pokemon && !pokemon.status) { - if (pokemon.trySetStatus(this.statusEffect, false, this.sourcePokemon)) { - if (this.turnsRemaining) { - pokemon.status!.sleepTurnsRemaining = this.turnsRemaining; - } - pokemon.updateInfo(true); - new CommonBattleAnim(CommonAnim.POISON + (this.statusEffect! - 1), pokemon).play(false, () => { - globalScene.phaseManager.queueMessage( - getStatusEffectObtainText( - this.statusEffect, - getPokemonNameWithAffix(pokemon), - this.sourceText ?? undefined, - ), - ); - if (!isNullOrUndefined(this.statusEffect) && this.statusEffect !== StatusEffect.FAINT) { - globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeStatusEffectTrigger, true); - // If mold breaker etc was used to set this status, it shouldn't apply to abilities activated afterwards - globalScene.arena.setIgnoreAbilities(false); - applyAbAttrs("PostSetStatusAbAttr", { - pokemon, - effect: this.statusEffect, - sourcePokemon: this.sourcePokemon ?? undefined, - }); - } - this.end(); + + pokemon.doSetStatus(this.statusEffect, this.sleepTurnsRemaining); + pokemon.updateInfo(true); + + new CommonBattleAnim(CommonAnim.POISON + (this.statusEffect - 1), pokemon).play(false, () => { + globalScene.phaseManager.queueMessage(this.statusMessage); + if (this.statusEffect && this.statusEffect !== StatusEffect.FAINT) { + globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeStatusEffectTrigger, true); + // If the status was applied from a move, ensure abilities are not ignored for follow-up triggers. + // TODO: Ensure this isn't breaking any other phases unshifted afterwards + globalScene.arena.setIgnoreAbilities(false); + applyAbAttrs("PostSetStatusAbAttr", { + pokemon, + effect: this.statusEffect, + sourcePokemon: this.sourcePokemon ?? undefined, }); - return; } - } else if (pokemon.status?.effect === this.statusEffect) { - globalScene.phaseManager.queueMessage( - getStatusEffectOverlapText(this.statusEffect ?? StatusEffect.NONE, getPokemonNameWithAffix(pokemon)), - ); - } - this.end(); + this.end(); + }); } } diff --git a/src/phases/pokemon-heal-phase.ts b/src/phases/pokemon-heal-phase.ts index fa6a3222466..02bb3a0b968 100644 --- a/src/phases/pokemon-heal-phase.ts +++ b/src/phases/pokemon-heal-phase.ts @@ -13,6 +13,7 @@ import { HealAchv } from "#system/achv"; import { NumberHolder } from "#utils/common"; import i18next from "i18next"; +// TODO: Refactor this - it has far too many arguments export class PokemonHealPhase extends CommonAnimPhase { public readonly phaseName = "PokemonHealPhase"; private hpHealed: number; @@ -28,7 +29,7 @@ export class PokemonHealPhase extends CommonAnimPhase { battlerIndex: BattlerIndex, hpHealed: number, message: string | null, - showFullHpMessage: boolean, + showFullHpMessage = true, skipAnim = false, revive = false, healStatus = false, @@ -72,6 +73,7 @@ export class PokemonHealPhase extends CommonAnimPhase { this.message = null; return super.end(); } + if (healOrDamage) { const hpRestoreMultiplier = new NumberHolder(1); if (!this.revive) { diff --git a/src/phases/post-summon-phase.ts b/src/phases/post-summon-phase.ts index e0811d0ab93..913a29cded8 100644 --- a/src/phases/post-summon-phase.ts +++ b/src/phases/post-summon-phase.ts @@ -1,6 +1,6 @@ import { applyAbAttrs } from "#abilities/apply-ab-attrs"; import { globalScene } from "#app/global-scene"; -import { ArenaTrapTag } from "#data/arena-tag"; +import { EntryHazardTag } from "#data/arena-tag"; import { MysteryEncounterPostSummonTag } from "#data/battler-tags"; import { BattlerTagType } from "#enums/battler-tag-type"; import { StatusEffect } from "#enums/status-effect"; @@ -16,7 +16,7 @@ export class PostSummonPhase extends PokemonPhase { if (pokemon.status?.effect === StatusEffect.TOXIC) { pokemon.status.toxicTurnCount = 0; } - globalScene.arena.applyTags(ArenaTrapTag, false, pokemon); + globalScene.arena.applyTags(EntryHazardTag, false, pokemon); // If this is mystery encounter and has post summon phase tag, apply post summon effects if ( diff --git a/src/phases/tera-phase.ts b/src/phases/tera-phase.ts index 84b05d88abe..5e42fab82ba 100644 --- a/src/phases/tera-phase.ts +++ b/src/phases/tera-phase.ts @@ -7,6 +7,7 @@ import { PokemonType } from "#enums/pokemon-type"; import type { Pokemon } from "#field/pokemon"; import { BattlePhase } from "#phases/battle-phase"; import { achvs } from "#system/achv"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; export class TeraPhase extends BattlePhase { @@ -25,7 +26,7 @@ export class TeraPhase extends BattlePhase { globalScene.phaseManager.queueMessage( i18next.t("battle:pokemonTerastallized", { pokemonNameWithAffix: getPokemonNameWithAffix(this.pokemon), - type: i18next.t(`pokemonInfo:Type.${PokemonType[this.pokemon.getTeraType()]}`), + type: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[this.pokemon.getTeraType()])}`), }), ); new CommonBattleAnim(CommonAnim.TERASTALLIZE, this.pokemon).play(false, () => { diff --git a/src/phases/turn-start-phase.ts b/src/phases/turn-start-phase.ts index 9c53a333ed0..8fc7a763c8f 100644 --- a/src/phases/turn-start-phase.ts +++ b/src/phases/turn-start-phase.ts @@ -1,4 +1,5 @@ import { applyAbAttrs } from "#abilities/apply-ab-attrs"; +import type { TurnCommand } from "#app/battle"; import { globalScene } from "#app/global-scene"; import { TrickRoomTag } from "#data/arena-tag"; import { allMoves } from "#data/data-lists"; @@ -14,19 +15,21 @@ import { BooleanHolder, randSeedShuffle } from "#utils/common"; export class TurnStartPhase extends FieldPhase { public readonly phaseName = "TurnStartPhase"; + /** - * This orders the active Pokemon on the field by speed into an BattlerIndex array and returns that array. + * Helper method to retrieve the current speed order of the combattants. * It also checks for Trick Room and reverses the array if it is present. - * @returns {@linkcode BattlerIndex[]} the battle indices of all pokemon on the field ordered by speed + * @returns The {@linkcode BattlerIndex}es of all on-field Pokemon, sorted in speed order. + * @todo Make this private */ getSpeedOrder(): BattlerIndex[] { - const playerField = globalScene.getPlayerField().filter(p => p.isActive()) as Pokemon[]; - const enemyField = globalScene.getEnemyField().filter(p => p.isActive()) as Pokemon[]; + const playerField = globalScene.getPlayerField().filter(p => p.isActive()); + const enemyField = globalScene.getEnemyField().filter(p => p.isActive()); - // We shuffle the list before sorting so speed ties produce random results - let orderedTargets: Pokemon[] = playerField.concat(enemyField); - // We seed it with the current turn to prevent an inconsistency where it - // was varying based on how long since you last reloaded + // Shuffle the list before sorting so speed ties produce random results + // This is seeded with the current turn to prevent turn order varying + // based on how long since you last reloaded. + let orderedTargets = (playerField as Pokemon[]).concat(enemyField); globalScene.executeWithSeedOffset( () => { orderedTargets = randSeedShuffle(orderedTargets); @@ -35,25 +38,25 @@ export class TurnStartPhase extends FieldPhase { globalScene.waveSeed, ); - // Next, a check for Trick Room is applied to determine sort order. + // Check for Trick Room and reverse sort order if active. + // Notably, Pokerogue does NOT have the "outspeed trick room" glitch at >1809 spd. const speedReversed = new BooleanHolder(false); globalScene.arena.applyTags(TrickRoomTag, false, speedReversed); - // Adjust the sort function based on whether Trick Room is active. orderedTargets.sort((a: Pokemon, b: Pokemon) => { - const aSpeed = a?.getEffectiveStat(Stat.SPD) ?? 0; - const bSpeed = b?.getEffectiveStat(Stat.SPD) ?? 0; + const aSpeed = a.getEffectiveStat(Stat.SPD); + const bSpeed = b.getEffectiveStat(Stat.SPD); return speedReversed.value ? aSpeed - bSpeed : bSpeed - aSpeed; }); - return orderedTargets.map(t => t.getFieldIndex() + (!t.isPlayer() ? BattlerIndex.ENEMY : BattlerIndex.PLAYER)); + return orderedTargets.map(t => t.getFieldIndex() + (t.isEnemy() ? BattlerIndex.ENEMY : BattlerIndex.PLAYER)); } /** - * This takes the result of getSpeedOrder and applies priority / bypass speed attributes to it. - * This also considers the priority levels of various commands and changes the result of getSpeedOrder based on such. - * @returns {@linkcode BattlerIndex[]} the final sequence of commands for this turn + * This takes the result of {@linkcode getSpeedOrder} and applies priority / bypass speed attributes to it. + * This also considers the priority levels of various commands and changes the result of `getSpeedOrder` based on such. + * @returns The `BattlerIndex`es of all on-field Pokemon sorted in action order. */ getCommandOrder(): BattlerIndex[] { let moveOrder = this.getSpeedOrder(); @@ -114,7 +117,8 @@ export class TurnStartPhase extends FieldPhase { } } - // If there is no difference between the move's calculated priorities, the game checks for differences in battlerBypassSpeed and returns the result. + // If there is no difference between the move's calculated priorities, + // check for differences in battlerBypassSpeed and returns the result. if (battlerBypassSpeed[a].value !== battlerBypassSpeed[b].value) { return battlerBypassSpeed[a].value ? -1 : 1; } @@ -135,8 +139,6 @@ export class TurnStartPhase extends FieldPhase { const field = globalScene.getField(); const moveOrder = this.getCommandOrder(); - let orderIndex = 0; - for (const o of this.getSpeedOrder()) { const pokemon = field[o]; const preTurnCommand = globalScene.currentBattle.preTurnCommands[o]; @@ -153,71 +155,24 @@ export class TurnStartPhase extends FieldPhase { const phaseManager = globalScene.phaseManager; - for (const o of moveOrder) { + moveOrder.forEach((o, index) => { const pokemon = field[o]; const turnCommand = globalScene.currentBattle.turnCommands[o]; - if (turnCommand?.skip) { - continue; + if (!turnCommand || turnCommand.skip) { + return; } - 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 && m.ppUsed < m.getMovePp()) ?? - new PokemonMove(queuedMove.move); - if (move.getMove().hasAttr("MoveHeaderAttr")) { - phaseManager.unshiftNew("MoveHeaderPhase", pokemon, move); - } - - if (pokemon.isPlayer() && turnCommand.cursor === -1) { - phaseManager.pushNew( - "MovePhase", - pokemon, - turnCommand.targets || turnCommand.move!.targets, - move, - turnCommand.move!.useMode, - ); //TODO: is the bang correct here? - } else { - phaseManager.pushNew( - "MovePhase", - pokemon, - turnCommand.targets || turnCommand.move!.targets, - move, - queuedMove.useMode, - ); // TODO: is the bang correct here? - } - break; - } - case Command.BALL: - phaseManager.unshiftNew("AttemptCapturePhase", 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; - phaseManager.unshiftNew( - "SwitchSummonPhase", - switchType, - pokemon.getFieldIndex(), - turnCommand.cursor!, - true, - pokemon.isPlayer(), - ); - } - break; - case Command.RUN: - { - // Running (like ball throwing) is a team action taking up both Pokemon's turns. - phaseManager.unshiftNew("AttemptRunPhase"); - } - break; + // TODO: Remove `turnData.order` - + // it is used exclusively for Fusion Flare/Bolt + // and uses a really jank (and incorrect) implementation + if (turnCommand.command === Command.FIGHT) { + pokemon.turnData.order = index; } - } + this.handleTurnCommand(turnCommand, pokemon); + }); + + // Queue various effects for the end of the turn. phaseManager.pushNew("CheckInterludePhase"); // TODO: Re-order these phases to be consistent with mainline turn order: @@ -239,4 +194,52 @@ export class TurnStartPhase extends FieldPhase { */ this.end(); } + + private handleTurnCommand(turnCommand: TurnCommand, pokemon: Pokemon) { + switch (turnCommand?.command) { + case Command.FIGHT: + this.handleFightCommand(turnCommand, pokemon); + break; + case Command.BALL: + globalScene.phaseManager.unshiftNew("AttemptCapturePhase", turnCommand.targets![0] % 2, turnCommand.cursor!); //TODO: is the bang correct here? + break; + case Command.POKEMON: + globalScene.phaseManager.unshiftNew( + "SwitchSummonPhase", + turnCommand.args?.[0] ? SwitchType.BATON_PASS : SwitchType.SWITCH, + pokemon.getFieldIndex(), + turnCommand.cursor!, // TODO: Is this bang correct? + true, + pokemon.isPlayer(), + ); + break; + case Command.RUN: + globalScene.phaseManager.unshiftNew("AttemptRunPhase"); + break; + } + } + + private handleFightCommand(turnCommand: TurnCommand, pokemon: Pokemon) { + const queuedMove = turnCommand.move; + if (!queuedMove) { + return; + } + + // TODO: This seems somewhat dubious + const move = + pokemon.getMoveset().find(m => m.moveId === queuedMove.move && m.ppUsed < m.getMovePp()) ?? + new PokemonMove(queuedMove.move); + + if (move.getMove().hasAttr("MoveHeaderAttr")) { + globalScene.phaseManager.unshiftNew("MoveHeaderPhase", pokemon, move); + } + + globalScene.phaseManager.pushNew( + "MovePhase", + pokemon, + turnCommand.targets ?? queuedMove.targets, + move, + queuedMove.useMode, + ); + } } diff --git a/src/system/achv.ts b/src/system/achv.ts index f238acbda3a..4e9bb54c304 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -15,6 +15,7 @@ import { TurnHeldItemTransferModifier } from "#modifiers/modifier"; import type { ConditionFn } from "#types/common"; import { isNuzlockeChallenge } from "#utils/challenge-utils"; import { NumberHolder } from "#utils/common"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; import type { Modifier } from "typescript"; @@ -42,13 +43,11 @@ export class Achv { constructor( localizationKey: string, - name: string, description: string, iconImage: string, score: number, conditionFunc?: ConditionFn, ) { - this.name = name; this.description = description; this.iconImage = iconImage; this.score = score; @@ -107,8 +106,8 @@ export class Achv { export class MoneyAchv extends Achv { moneyAmount: number; - constructor(localizationKey: string, name: string, moneyAmount: number, iconImage: string, score: number) { - super(localizationKey, name, "", iconImage, score, (_args: any[]) => globalScene.money >= this.moneyAmount); + constructor(localizationKey: string, moneyAmount: number, iconImage: string, score: number) { + super(localizationKey, "", iconImage, score, (_args: any[]) => globalScene.money >= this.moneyAmount); this.moneyAmount = moneyAmount; } } @@ -116,10 +115,9 @@ export class MoneyAchv extends Achv { export class RibbonAchv extends Achv { ribbonAmount: number; - constructor(localizationKey: string, name: string, ribbonAmount: number, iconImage: string, score: number) { + constructor(localizationKey: string, ribbonAmount: number, iconImage: string, score: number) { super( localizationKey, - name, "", iconImage, score, @@ -132,10 +130,9 @@ export class RibbonAchv extends Achv { export class DamageAchv extends Achv { damageAmount: number; - constructor(localizationKey: string, name: string, damageAmount: number, iconImage: string, score: number) { + constructor(localizationKey: string, damageAmount: number, iconImage: string, score: number) { super( localizationKey, - name, "", iconImage, score, @@ -148,10 +145,9 @@ export class DamageAchv extends Achv { export class HealAchv extends Achv { healAmount: number; - constructor(localizationKey: string, name: string, healAmount: number, iconImage: string, score: number) { + constructor(localizationKey: string, healAmount: number, iconImage: string, score: number) { super( localizationKey, - name, "", iconImage, score, @@ -164,10 +160,9 @@ export class HealAchv extends Achv { export class LevelAchv extends Achv { level: number; - constructor(localizationKey: string, name: string, level: number, iconImage: string, score: number) { + constructor(localizationKey: string, level: number, iconImage: string, score: number) { super( localizationKey, - name, "", iconImage, score, @@ -180,26 +175,24 @@ export class LevelAchv extends Achv { export class ModifierAchv extends Achv { constructor( localizationKey: string, - name: string, description: string, iconImage: string, score: number, modifierFunc: (modifier: Modifier) => boolean, ) { - super(localizationKey, name, description, iconImage, score, (args: any[]) => modifierFunc(args[0] as Modifier)); + super(localizationKey, description, iconImage, score, (args: any[]) => modifierFunc(args[0] as Modifier)); } } export class ChallengeAchv extends Achv { constructor( localizationKey: string, - name: string, description: string, iconImage: string, score: number, challengeFunc: (challenge: Challenge) => boolean, ) { - super(localizationKey, name, description, iconImage, score, (args: any[]) => challengeFunc(args[0] as Challenge)); + super(localizationKey, description, iconImage, score, (args: any[]) => challengeFunc(args[0] as Challenge)); } } @@ -214,330 +207,342 @@ export function getAchievementDescription(localizationKey: string): string { const genderStr = PlayerGender[genderIndex].toLowerCase(); switch (localizationKey) { - case "10K_MONEY": - return i18next.t("achv:MoneyAchv.description", { + case "10KMoney": + 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", { + case "100KMoney": + 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", { + case "1MMoney": + 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", { + case "10MMoney": + 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", { + case "250Dmg": + 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", { + case "1000Dmg": + 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", { + case "2500Dmg": + 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", { + case "10000Dmg": + 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", { + case "250Heal": + 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", { + case "1000Heal": + 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", { + case "2500Heal": + 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", { + case "10000Heal": + 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", { + case "lv100": + return i18next.t("achv:levelAchv.description", { context: genderStr, level: achvs.LV_100.level, }); - case "LV_250": - return i18next.t("achv:LevelAchv.description", { + case "lv250": + return i18next.t("achv:levelAchv.description", { context: genderStr, level: achvs.LV_250.level, }); - case "LV_1000": - return i18next.t("achv:LevelAchv.description", { + case "lv1000": + return i18next.t("achv:levelAchv.description", { context: genderStr, level: achvs.LV_1000.level, }); - case "10_RIBBONS": - return i18next.t("achv:RibbonAchv.description", { + case "10Ribbons": + 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", { + case "25Ribbons": + 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", { + case "50Ribbons": + 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", { + case "75Ribbons": + 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", { + case "100Ribbons": + 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", { + case "transferMaxStatStage": + return i18next.t("achv:transferMaxStatStage.description", { context: genderStr, }); - case "MAX_FRIENDSHIP": - return i18next.t("achv:MAX_FRIENDSHIP.description", { + case "maxFriendship": + return i18next.t("achv:maxFriendship.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", { + case "megaEvolve": + return i18next.t("achv:megaEvolve.description", { context: genderStr }); + case "gigantamax": + return i18next.t("achv:gigantamax.description", { context: genderStr }); + case "terastallize": + return i18next.t("achv:terastallize.description", { context: genderStr }); + case "stellarTerastallize": + return i18next.t("achv:stellarTerastallize.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", { + case "splice": + return i18next.t("achv:splice.description", { context: genderStr }); + case "miniBlackHole": + return i18next.t("achv:miniBlackHole.description", { context: genderStr, }); - case "CATCH_MYTHICAL": - return i18next.t("achv:CATCH_MYTHICAL.description", { + case "catchMythical": + return i18next.t("achv:catchMythical.description", { context: genderStr, }); - case "CATCH_SUB_LEGENDARY": - return i18next.t("achv:CATCH_SUB_LEGENDARY.description", { + case "catchSubLegendary": + return i18next.t("achv:catchSubLegendary.description", { context: genderStr, }); - case "CATCH_LEGENDARY": - return i18next.t("achv:CATCH_LEGENDARY.description", { + case "catchLegendary": + return i18next.t("achv:catchLegendary.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", { + case "seeShiny": + return i18next.t("achv:seeShiny.description", { context: genderStr }); + case "shinyParty": + return i18next.t("achv:shinyParty.description", { context: genderStr }); + case "hatchMythical": + return i18next.t("achv:hatchMythical.description", { context: genderStr, }); - case "HATCH_SUB_LEGENDARY": - return i18next.t("achv:HATCH_SUB_LEGENDARY.description", { + case "hatchSubLegendary": + return i18next.t("achv:hatchSubLegendary.description", { context: genderStr, }); - case "HATCH_LEGENDARY": - return i18next.t("achv:HATCH_LEGENDARY.description", { + case "hatchLegendary": + return i18next.t("achv:hatchLegendary.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", { + case "hatchShiny": + return i18next.t("achv:hatchShiny.description", { context: genderStr }); + case "hiddenAbility": + return i18next.t("achv:hiddenAbility.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", { + case "perfectIvs": + return i18next.t("achv:perfectIvs.description", { context: genderStr }); + case "classicVictory": + return i18next.t("achv:classicVictory.description", { context: genderStr, }); - case "UNEVOLVED_CLASSIC_VICTORY": - return i18next.t("achv:UNEVOLVED_CLASSIC_VICTORY.description", { + case "unevolvedClassicVictory": + return i18next.t("achv:unevolvedClassicVictory.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", { + case "monoGenOne": + return i18next.t("achv:monoGenOne.description", { context: genderStr }); + case "monoGenTwo": + return i18next.t("achv:monoGenTwo.description", { context: genderStr }); + case "monoGenThree": + return i18next.t("achv:monoGenThree.description", { context: genderStr, }); - case "MONO_GEN_FOUR": - return i18next.t("achv:MONO_GEN_FOUR.description", { + case "monoGenFour": + return i18next.t("achv:monoGenFour.description", { context: genderStr, }); - case "MONO_GEN_FIVE": - return i18next.t("achv:MONO_GEN_FIVE.description", { + case "monoGenFive": + return i18next.t("achv:monoGenFive.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", { + case "monoGenSix": + return i18next.t("achv:monoGenSix.description", { context: genderStr }); + case "monoGenSeven": + return i18next.t("achv:monoGenSeven.description", { context: genderStr, }); - case "MONO_GEN_EIGHT": - return i18next.t("achv:MONO_GEN_EIGHT.description", { + case "monoGenEight": + return i18next.t("achv:monoGenEight.description", { context: genderStr, }); - case "MONO_GEN_NINE": - return i18next.t("achv:MONO_GEN_NINE.description", { + case "monoGenNine": + return i18next.t("achv:monoGenNine.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", { + case "monoNormal": + case "monoFighting": + case "monoFlying": + case "monoPoison": + case "monoGround": + case "monoRock": + case "monoBug": + case "monoGhost": + case "monoSteel": + case "monoFire": + case "monoWater": + case "monoGrass": + case "monoElectric": + case "monoPsychic": + case "monoIce": + case "monoDragon": + case "monoDark": + case "monoFairy": + return i18next.t("achv:monoType.description", { context: genderStr, - type: i18next.t(`pokemonInfo:Type.${localizationKey.slice(5)}`), + type: i18next.t(`pokemonInfo:type.${toCamelCase(localizationKey.slice(4))}`), }); - case "FRESH_START": - return i18next.t("achv:FRESH_START.description", { context: genderStr }); - case "INVERSE_BATTLE": - return i18next.t("achv:INVERSE_BATTLE.description", { + case "freshStart": + return i18next.t("achv:freshStart.description", { context: genderStr }); + case "inverseBattle": + return i18next.t("achv:inverseBattle.description", { context: genderStr, }); - case "FLIP_STATS": - return i18next.t("achv:FLIP_STATS.description", { context: genderStr }); - case "FLIP_INVERSE": - return i18next.t("achv:FLIP_INVERSE.description", { context: genderStr }); - case "NUZLOCKE": - return i18next.t("achv:NUZLOCKE.description", { context: genderStr }); - case "BREEDERS_IN_SPACE": - return i18next.t("achv:BREEDERS_IN_SPACE.description", { + case "flipStats": + return i18next.t("achv:flipStats.description", { context: genderStr }); + case "flipInverse": + return i18next.t("achv:flipInverse.description", { context: genderStr }); + case "nuzlocke": + return i18next.t("achv:nuzlocke.description", { context: genderStr }); + case "breedersInSpace": + return i18next.t("achv:breedersInSpace.description", { context: genderStr, }); + case "dailyVictory": + return i18next.t("achv:dailyVictory.description", { context: genderStr }); default: return ""; } } export const achvs = { - _10K_MONEY: new MoneyAchv("10K_MONEY", "", 10000, "nugget", 10), - _100K_MONEY: new MoneyAchv("100K_MONEY", "", 100000, "big_nugget", 25).setSecret(true), - _1M_MONEY: new MoneyAchv("1M_MONEY", "", 1000000, "relic_gold", 50).setSecret(true), - _10M_MONEY: new MoneyAchv("10M_MONEY", "", 10000000, "coin_case", 100).setSecret(true), - _250_DMG: new DamageAchv("250_DMG", "", 250, "lucky_punch", 10), - _1000_DMG: new DamageAchv("1000_DMG", "", 1000, "lucky_punch_great", 25).setSecret(true), - _2500_DMG: new DamageAchv("2500_DMG", "", 2500, "lucky_punch_ultra", 50).setSecret(true), - _10000_DMG: new DamageAchv("10000_DMG", "", 10000, "lucky_punch_master", 100).setSecret(true), - _250_HEAL: new HealAchv("250_HEAL", "", 250, "potion", 10), - _1000_HEAL: new HealAchv("1000_HEAL", "", 1000, "super_potion", 25).setSecret(true), - _2500_HEAL: new HealAchv("2500_HEAL", "", 2500, "hyper_potion", 50).setSecret(true), - _10000_HEAL: new HealAchv("10000_HEAL", "", 10000, "max_potion", 100).setSecret(true), - LV_100: new LevelAchv("LV_100", "", 100, "rare_candy", 25).setSecret(), - LV_250: new LevelAchv("LV_250", "", 250, "rarer_candy", 50).setSecret(true), - LV_1000: new LevelAchv("LV_1000", "", 1000, "candy_jar", 100).setSecret(true), - _10_RIBBONS: new RibbonAchv("10_RIBBONS", "", 10, "bronze_ribbon", 10), - _25_RIBBONS: new RibbonAchv("25_RIBBONS", "", 25, "great_ribbon", 25).setSecret(true), - _50_RIBBONS: new RibbonAchv("50_RIBBONS", "", 50, "ultra_ribbon", 50).setSecret(true), - _75_RIBBONS: new RibbonAchv("75_RIBBONS", "", 75, "rogue_ribbon", 75).setSecret(true), - _100_RIBBONS: new RibbonAchv("100_RIBBONS", "", 100, "master_ribbon", 100).setSecret(true), - TRANSFER_MAX_STAT_STAGE: new Achv("TRANSFER_MAX_STAT_STAGE", "", "TRANSFER_MAX_STAT_STAGE.description", "baton", 20), - MAX_FRIENDSHIP: new Achv("MAX_FRIENDSHIP", "", "MAX_FRIENDSHIP.description", "soothe_bell", 25), - MEGA_EVOLVE: new Achv("MEGA_EVOLVE", "", "MEGA_EVOLVE.description", "mega_bracelet", 50), - GIGANTAMAX: new Achv("GIGANTAMAX", "", "GIGANTAMAX.description", "dynamax_band", 50), - TERASTALLIZE: new Achv("TERASTALLIZE", "", "TERASTALLIZE.description", "tera_orb", 25), + CLASSIC_VICTORY: new Achv( + "classicVictory", + "classicVictory.description", + "relic_crown", + 250, + _ => globalScene.gameData.gameStats.sessionsWon === 0, + ), + _10_RIBBONS: new RibbonAchv("10Ribbons", 10, "common_ribbon", 50), + _25_RIBBONS: new RibbonAchv("25Ribbons", 25, "great_ribbon", 75), + _50_RIBBONS: new RibbonAchv("50Ribbons", 50, "ultra_ribbon", 100), + _75_RIBBONS: new RibbonAchv("75Ribbons", 75, "rogue_ribbon", 125), + _100_RIBBONS: new RibbonAchv("100Ribbons", 100, "master_ribbon", 150), + _10K_MONEY: new MoneyAchv("10KMoney", 10000, "nugget", 25), + _100K_MONEY: new MoneyAchv("100KMoney", 100000, "big_nugget", 25).setSecret(true), + _1M_MONEY: new MoneyAchv("1MMoney", 1000000, "relic_gold", 50).setSecret(true), + _10M_MONEY: new MoneyAchv("10MMoney", 10000000, "coin_case", 50).setSecret(true), + _250_DMG: new DamageAchv("250Dmg", 250, "lucky_punch", 25), + _1000_DMG: new DamageAchv("1000Dmg", 1000, "lucky_punch_great", 25).setSecret(true), + _2500_DMG: new DamageAchv("2500Dmg", 2500, "lucky_punch_ultra", 50).setSecret(true), + _10000_DMG: new DamageAchv("10000Dmg", 10000, "lucky_punch_master", 50).setSecret(true), + _250_HEAL: new HealAchv("250Heal", 250, "potion", 25), + _1000_HEAL: new HealAchv("1000Heal", 1000, "super_potion", 25).setSecret(true), + _2500_HEAL: new HealAchv("2500Heal", 2500, "hyper_potion", 50).setSecret(true), + _10000_HEAL: new HealAchv("10000Heal", 10000, "max_potion", 50).setSecret(true), + LV_100: new LevelAchv("lv100", 100, "rare_candy", 25).setSecret(), + LV_250: new LevelAchv("lv250", 250, "rarer_candy", 25).setSecret(true), + LV_1000: new LevelAchv("lv1000", 1000, "candy_jar", 50).setSecret(true), + TRANSFER_MAX_STAT_STAGE: new Achv("transferMaxStatStage", "transferMaxStatStage.description", "baton", 25), + MAX_FRIENDSHIP: new Achv("maxFriendship", "maxFriendship.description", "soothe_bell", 25), + MEGA_EVOLVE: new Achv("megaEvolve", "megaEvolve.description", "mega_bracelet", 50), + GIGANTAMAX: new Achv("gigantamax", "gigantamax.description", "dynamax_band", 50), + TERASTALLIZE: new Achv("terastallize", "terastallize.description", "tera_orb", 25), STELLAR_TERASTALLIZE: new Achv( - "STELLAR_TERASTALLIZE", - "", - "STELLAR_TERASTALLIZE.description", + "stellarTerastallize", + "stellarTerastallize.description", "stellar_tera_shard", 25, ).setSecret(true), - SPLICE: new Achv("SPLICE", "", "SPLICE.description", "dna_splicers", 10), + SPLICE: new Achv("splice", "splice.description", "dna_splicers", 50), MINI_BLACK_HOLE: new ModifierAchv( - "MINI_BLACK_HOLE", - "", - "MINI_BLACK_HOLE.description", + "miniBlackHole", + "miniBlackHole.description", "mini_black_hole", 25, modifier => modifier instanceof TurnHeldItemTransferModifier, ).setSecret(), - CATCH_MYTHICAL: new Achv("CATCH_MYTHICAL", "", "CATCH_MYTHICAL.description", "strange_ball", 50).setSecret(), - CATCH_SUB_LEGENDARY: new Achv("CATCH_SUB_LEGENDARY", "", "CATCH_SUB_LEGENDARY.description", "rb", 75).setSecret(), - CATCH_LEGENDARY: new Achv("CATCH_LEGENDARY", "", "CATCH_LEGENDARY.description", "mb", 100).setSecret(), - SEE_SHINY: new Achv("SEE_SHINY", "", "SEE_SHINY.description", "pb_gold", 75), - SHINY_PARTY: new Achv("SHINY_PARTY", "", "SHINY_PARTY.description", "shiny_charm", 100).setSecret(true), - HATCH_MYTHICAL: new Achv("HATCH_MYTHICAL", "", "HATCH_MYTHICAL.description", "mystery_egg", 75).setSecret(), - HATCH_SUB_LEGENDARY: new Achv( - "HATCH_SUB_LEGENDARY", - "", - "HATCH_SUB_LEGENDARY.description", - "oval_stone", + HIDDEN_ABILITY: new Achv("hiddenAbility", "hiddenAbility.description", "ability_charm", 25), + PERFECT_IVS: new Achv("perfectIvs", "perfectIvs.description", "blunder_policy", 25), + SEE_SHINY: new Achv("seeShiny", "seeShiny.description", "pb_gold", 50), + SHINY_PARTY: new Achv("shinyParty", "shinyParty.description", "shiny_charm", 50).setSecret(true), + CATCH_SUB_LEGENDARY: new Achv("catchSubLegendary", "catchSubLegendary.description", "rb", 50).setSecret(), + CATCH_MYTHICAL: new Achv("catchMythical", "catchMythical.description", "strange_ball", 75).setSecret(), + CATCH_LEGENDARY: new Achv("catchLegendary", "catchLegendary.description", "mb", 100).setSecret(), + HATCH_SUB_LEGENDARY: new Achv("hatchSubLegendary", "hatchSubLegendary.description", "epic_egg", 50).setSecret(), + HATCH_MYTHICAL: new Achv("hatchMythical", "hatchMythical.description", "manaphy_egg", 50).setSecret(), + HATCH_LEGENDARY: new Achv("hatchLegendary", "hatchLegendary.description", "legendary_egg", 100).setSecret(), + HATCH_SHINY: new Achv("hatchShiny", "hatchShiny.description", "rogue_egg", 100).setSecret(), + DAILY_VICTORY: new Achv("dailyVictory", "dailyVictory.description", "calendar", 100), + FRESH_START: new ChallengeAchv( + "freshStart", + "freshStart.description", + "reviver_seed", 100, - ).setSecret(), - HATCH_LEGENDARY: new Achv("HATCH_LEGENDARY", "", "HATCH_LEGENDARY.description", "lucky_egg", 125).setSecret(), - HATCH_SHINY: new Achv("HATCH_SHINY", "", "HATCH_SHINY.description", "golden_egg", 100).setSecret(), - HIDDEN_ABILITY: new Achv("HIDDEN_ABILITY", "", "HIDDEN_ABILITY.description", "ability_charm", 75), - PERFECT_IVS: new Achv("PERFECT_IVS", "", "PERFECT_IVS.description", "blunder_policy", 100), - CLASSIC_VICTORY: new Achv( - "CLASSIC_VICTORY", - "", - "CLASSIC_VICTORY.description", - "relic_crown", - 150, - _ => globalScene.gameData.gameStats.sessionsWon === 0, + c => + c instanceof FreshStartChallenge && + c.value === 1 && + !globalScene.gameMode.challenges.some( + c => [Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT].includes(c.id) && c.value > 0, + ), ), - UNEVOLVED_CLASSIC_VICTORY: new Achv( - "UNEVOLVED_CLASSIC_VICTORY", - "", - "UNEVOLVED_CLASSIC_VICTORY.description", - "eviolite", - 175, - _ => globalScene.getPlayerParty().some(p => p.getSpeciesForm(true).speciesId in pokemonEvolutions), + NUZLOCKE: new ChallengeAchv("nuzlocke", "nuzlocke.description", "leaf_stone", 100, isNuzlockeChallenge), + INVERSE_BATTLE: new ChallengeAchv( + "inverseBattle", + "inverseBattle.description", + "inverse", + 100, + c => c instanceof InverseBattleChallenge && c.value > 0, + ), + FLIP_STATS: new ChallengeAchv( + "flipStats", + "flipStats.description", + "dubious_disc", + 100, + c => c instanceof FlipStatChallenge && c.value > 0, ), MONO_GEN_ONE_VICTORY: new ChallengeAchv( - "MONO_GEN_ONE", - "", - "MONO_GEN_ONE.description", + "monoGenOne", + "monoGenOne.description", "ribbon_gen1", 100, c => @@ -548,9 +553,8 @@ export const achvs = { ), ), MONO_GEN_TWO_VICTORY: new ChallengeAchv( - "MONO_GEN_TWO", - "", - "MONO_GEN_TWO.description", + "monoGenTwo", + "monoGenTwo.description", "ribbon_gen2", 100, c => @@ -561,9 +565,8 @@ export const achvs = { ), ), MONO_GEN_THREE_VICTORY: new ChallengeAchv( - "MONO_GEN_THREE", - "", - "MONO_GEN_THREE.description", + "monoGenThree", + "monoGenThree.description", "ribbon_gen3", 100, c => @@ -574,9 +577,8 @@ export const achvs = { ), ), MONO_GEN_FOUR_VICTORY: new ChallengeAchv( - "MONO_GEN_FOUR", - "", - "MONO_GEN_FOUR.description", + "monoGenFour", + "monoGenFour.description", "ribbon_gen4", 100, c => @@ -587,9 +589,8 @@ export const achvs = { ), ), MONO_GEN_FIVE_VICTORY: new ChallengeAchv( - "MONO_GEN_FIVE", - "", - "MONO_GEN_FIVE.description", + "monoGenFive", + "monoGenFive.description", "ribbon_gen5", 100, c => @@ -600,9 +601,8 @@ export const achvs = { ), ), MONO_GEN_SIX_VICTORY: new ChallengeAchv( - "MONO_GEN_SIX", - "", - "MONO_GEN_SIX.description", + "monoGenSix", + "monoGenSix.description", "ribbon_gen6", 100, c => @@ -613,9 +613,8 @@ export const achvs = { ), ), MONO_GEN_SEVEN_VICTORY: new ChallengeAchv( - "MONO_GEN_SEVEN", - "", - "MONO_GEN_SEVEN.description", + "monoGenSeven", + "monoGenSeven.description", "ribbon_gen7", 100, c => @@ -626,9 +625,8 @@ export const achvs = { ), ), MONO_GEN_EIGHT_VICTORY: new ChallengeAchv( - "MONO_GEN_EIGHT", - "", - "MONO_GEN_EIGHT.description", + "monoGenEight", + "monoGenEight.description", "ribbon_gen8", 100, c => @@ -639,9 +637,8 @@ export const achvs = { ), ), MONO_GEN_NINE_VICTORY: new ChallengeAchv( - "MONO_GEN_NINE", - "", - "MONO_GEN_NINE.description", + "monoGenNine", + "monoGenNine.description", "ribbon_gen9", 100, c => @@ -652,9 +649,8 @@ export const achvs = { ), ), MONO_NORMAL: new ChallengeAchv( - "MONO_NORMAL", - "", - "MONO_NORMAL.description", + "monoNormal", + "monoNormal.description", "silk_scarf", 100, c => @@ -665,9 +661,8 @@ export const achvs = { ), ), MONO_FIGHTING: new ChallengeAchv( - "MONO_FIGHTING", - "", - "MONO_FIGHTING.description", + "monoFighting", + "monoFighting.description", "black_belt", 100, c => @@ -678,9 +673,8 @@ export const achvs = { ), ), MONO_FLYING: new ChallengeAchv( - "MONO_FLYING", - "", - "MONO_FLYING.description", + "monoFlying", + "monoFlying.description", "sharp_beak", 100, c => @@ -691,9 +685,8 @@ export const achvs = { ), ), MONO_POISON: new ChallengeAchv( - "MONO_POISON", - "", - "MONO_POISON.description", + "monoPoison", + "monoPoison.description", "poison_barb", 100, c => @@ -704,9 +697,8 @@ export const achvs = { ), ), MONO_GROUND: new ChallengeAchv( - "MONO_GROUND", - "", - "MONO_GROUND.description", + "monoGround", + "monoGround.description", "soft_sand", 100, c => @@ -717,9 +709,8 @@ export const achvs = { ), ), MONO_ROCK: new ChallengeAchv( - "MONO_ROCK", - "", - "MONO_ROCK.description", + "monoRock", + "monoRock.description", "hard_stone", 100, c => @@ -730,9 +721,8 @@ export const achvs = { ), ), MONO_BUG: new ChallengeAchv( - "MONO_BUG", - "", - "MONO_BUG.description", + "monoBug", + "monoBug.description", "silver_powder", 100, c => @@ -743,9 +733,8 @@ export const achvs = { ), ), MONO_GHOST: new ChallengeAchv( - "MONO_GHOST", - "", - "MONO_GHOST.description", + "monoGhost", + "monoGhost.description", "spell_tag", 100, c => @@ -756,9 +745,8 @@ export const achvs = { ), ), MONO_STEEL: new ChallengeAchv( - "MONO_STEEL", - "", - "MONO_STEEL.description", + "monoSteel", + "monoSteel.description", "metal_coat", 100, c => @@ -769,9 +757,8 @@ export const achvs = { ), ), MONO_FIRE: new ChallengeAchv( - "MONO_FIRE", - "", - "MONO_FIRE.description", + "monoFire", + "monoFire.description", "charcoal", 100, c => @@ -782,9 +769,8 @@ export const achvs = { ), ), MONO_WATER: new ChallengeAchv( - "MONO_WATER", - "", - "MONO_WATER.description", + "monoWater", + "monoWater.description", "mystic_water", 100, c => @@ -795,9 +781,8 @@ export const achvs = { ), ), MONO_GRASS: new ChallengeAchv( - "MONO_GRASS", - "", - "MONO_GRASS.description", + "monoGrass", + "monoGrass.description", "miracle_seed", 100, c => @@ -808,9 +793,8 @@ export const achvs = { ), ), MONO_ELECTRIC: new ChallengeAchv( - "MONO_ELECTRIC", - "", - "MONO_ELECTRIC.description", + "monoElectric", + "monoElectric.description", "magnet", 100, c => @@ -821,9 +805,8 @@ export const achvs = { ), ), MONO_PSYCHIC: new ChallengeAchv( - "MONO_PSYCHIC", - "", - "MONO_PSYCHIC.description", + "monoPsychic", + "monoPsychic.description", "twisted_spoon", 100, c => @@ -834,9 +817,8 @@ export const achvs = { ), ), MONO_ICE: new ChallengeAchv( - "MONO_ICE", - "", - "MONO_ICE.description", + "monoIce", + "monoIce.description", "never_melt_ice", 100, c => @@ -847,9 +829,8 @@ export const achvs = { ), ), MONO_DRAGON: new ChallengeAchv( - "MONO_DRAGON", - "", - "MONO_DRAGON.description", + "monoDragon", + "monoDragon.description", "dragon_fang", 100, c => @@ -860,9 +841,8 @@ export const achvs = { ), ), MONO_DARK: new ChallengeAchv( - "MONO_DARK", - "", - "MONO_DARK.description", + "monoDark", + "monoDark.description", "black_glasses", 100, c => @@ -873,9 +853,8 @@ export const achvs = { ), ), MONO_FAIRY: new ChallengeAchv( - "MONO_FAIRY", - "", - "MONO_FAIRY.description", + "monoFairy", + "monoFairy.description", "fairy_feather", 100, c => @@ -885,49 +864,24 @@ export const achvs = { c => [Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT].includes(c.id) && c.value > 0, ), ), - FRESH_START: new ChallengeAchv( - "FRESH_START", - "", - "FRESH_START.description", - "reviver_seed", - 100, - c => - c instanceof FreshStartChallenge && - c.value === 1 && - !globalScene.gameMode.challenges.some( - c => [Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT].includes(c.id) && c.value > 0, - ), - ), - INVERSE_BATTLE: new ChallengeAchv( - "INVERSE_BATTLE", - "", - "INVERSE_BATTLE.description", - "inverse", - 100, - c => c instanceof InverseBattleChallenge && c.value > 0, - ), - FLIP_STATS: new ChallengeAchv( - "FLIP_STATS", - "", - "FLIP_STATS.description", - "dubious_disc", - 100, - c => c instanceof FlipStatChallenge && c.value > 0, + UNEVOLVED_CLASSIC_VICTORY: new Achv( + "unevolvedClassicVictory", + "unevolvedClassicVictory.description", + "eviolite", + 50, + _ => globalScene.getPlayerParty().some(p => p.getSpeciesForm(true).speciesId in pokemonEvolutions), ), FLIP_INVERSE: new ChallengeAchv( - "FLIP_INVERSE", - "", - "FLIP_INVERSE.description", + "flipInverse", + "flipInverse.description", "cracked_pot", - 100, + 50, c => c instanceof FlipStatChallenge && c.value > 0 && globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0), ).setSecret(), - // TODO: Decide on icon - NUZLOCKE: new ChallengeAchv("NUZLOCKE", "", "NUZLOCKE.description", "leaf_stone", 100, isNuzlockeChallenge), - BREEDERS_IN_SPACE: new Achv("BREEDERS_IN_SPACE", "", "BREEDERS_IN_SPACE.description", "moon_stone", 50).setSecret(), + BREEDERS_IN_SPACE: new Achv("breedersInSpace", "breedersInSpace.description", "moon_stone", 50).setSecret(), }; export function initAchievements() { diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 90cbf6e18cc..3a4dafb2de2 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -10,7 +10,7 @@ import { Tutorial } from "#app/tutorial"; import { speciesEggMoves } from "#balance/egg-moves"; import { pokemonPrevolutions } from "#balance/pokemon-evolutions"; import { speciesStarterCosts } from "#balance/starters"; -import { ArenaTrapTag } from "#data/arena-tag"; +import { EntryHazardTag } from "#data/arena-tag"; import { allMoves, allSpecies } from "#data/data-lists"; import type { Egg } from "#data/egg"; import { pokemonFormChanges } from "#data/pokemon-forms"; @@ -1135,8 +1135,8 @@ export class GameData { globalScene.arena.tags = sessionData.arena.tags; if (globalScene.arena.tags) { for (const tag of globalScene.arena.tags) { - if (tag instanceof ArenaTrapTag) { - const { tagType, side, turnCount, layers, maxLayers } = tag as ArenaTrapTag; + if (tag instanceof EntryHazardTag) { + const { tagType, side, turnCount, layers, maxLayers } = tag as EntryHazardTag; globalScene.arena.eventTarget.dispatchEvent( new TagAddedEvent(tagType, side, turnCount, layers, maxLayers), ); @@ -2103,13 +2103,13 @@ export class GameData { }; } - getStarterSpeciesDefaultAbilityIndex(species: PokemonSpecies): number { - const abilityAttr = this.starterData[species.speciesId].abilityAttr; + getStarterSpeciesDefaultAbilityIndex(species: PokemonSpecies, abilityAttr?: number): number { + abilityAttr ??= this.starterData[species.speciesId].abilityAttr; return abilityAttr & AbilityAttr.ABILITY_1 ? 0 : !species.ability2 || abilityAttr & AbilityAttr.ABILITY_2 ? 1 : 2; } - getSpeciesDefaultNature(species: PokemonSpecies): Nature { - const dexEntry = this.dexData[species.speciesId]; + getSpeciesDefaultNature(species: PokemonSpecies, dexEntry?: DexEntry): Nature { + dexEntry ??= this.dexData[species.speciesId]; for (let n = 0; n < 25; n++) { if (dexEntry.natureAttr & (1 << (n + 1))) { return n as Nature; diff --git a/src/system/ribbons/ribbon-data.ts b/src/system/ribbons/ribbon-data.ts index 42c523afc0e..27e68a36a15 100644 --- a/src/system/ribbons/ribbon-data.ts +++ b/src/system/ribbons/ribbon-data.ts @@ -1,6 +1,6 @@ import type { Brander } from "#types/type-helpers"; -export type RibbonFlag = (number & Brander<"RibbonFlag">) | 0; +export type RibbonFlag = (bigint & Brander<"RibbonFlag">) | 0n; /** * Class for ribbon data management. Usually constructed via the {@linkcode fromJSON} method. @@ -10,91 +10,91 @@ export type RibbonFlag = (number & Brander<"RibbonFlag">) | 0; */ export class RibbonData { /** Internal bitfield storing the unlock state for each ribbon */ - private payload: number; + private payload: bigint; //#region Ribbons //#region Monotype challenge ribbons /** Ribbon for winning the normal monotype challenge */ - public static readonly MONO_NORMAL = 0x1 as RibbonFlag; + public static readonly MONO_NORMAL = 0x1n as RibbonFlag; /** Ribbon for winning the fighting monotype challenge */ - public static readonly MONO_FIGHTING = 0x2 as RibbonFlag; + public static readonly MONO_FIGHTING = 0x2n as RibbonFlag; /** Ribbon for winning the flying monotype challenge */ - public static readonly MONO_FLYING = 0x4 as RibbonFlag; + public static readonly MONO_FLYING = 0x4n as RibbonFlag; /** Ribbon for winning the poision monotype challenge */ - public static readonly MONO_POISON = 0x8 as RibbonFlag; + public static readonly MONO_POISON = 0x8n as RibbonFlag; /** Ribbon for winning the ground monotype challenge */ - public static readonly MONO_GROUND = 0x10 as RibbonFlag; + public static readonly MONO_GROUND = 0x10n as RibbonFlag; /** Ribbon for winning the rock monotype challenge */ - public static readonly MONO_ROCK = 0x20 as RibbonFlag; + public static readonly MONO_ROCK = 0x20n as RibbonFlag; /** Ribbon for winning the bug monotype challenge */ - public static readonly MONO_BUG = 0x40 as RibbonFlag; + public static readonly MONO_BUG = 0x40n as RibbonFlag; /** Ribbon for winning the ghost monotype challenge */ - public static readonly MONO_GHOST = 0x80 as RibbonFlag; + public static readonly MONO_GHOST = 0x80n as RibbonFlag; /** Ribbon for winning the steel monotype challenge */ - public static readonly MONO_STEEL = 0x100 as RibbonFlag; + public static readonly MONO_STEEL = 0x100n as RibbonFlag; /** Ribbon for winning the fire monotype challenge */ - public static readonly MONO_FIRE = 0x200 as RibbonFlag; + public static readonly MONO_FIRE = 0x200n as RibbonFlag; /** Ribbon for winning the water monotype challenge */ - public static readonly MONO_WATER = 0x400 as RibbonFlag; + public static readonly MONO_WATER = 0x400n as RibbonFlag; /** Ribbon for winning the grass monotype challenge */ - public static readonly MONO_GRASS = 0x800 as RibbonFlag; + public static readonly MONO_GRASS = 0x800n as RibbonFlag; /** Ribbon for winning the electric monotype challenge */ - public static readonly MONO_ELECTRIC = 0x1000 as RibbonFlag; + public static readonly MONO_ELECTRIC = 0x1000n as RibbonFlag; /** Ribbon for winning the psychic monotype challenge */ - public static readonly MONO_PSYCHIC = 0x2000 as RibbonFlag; + public static readonly MONO_PSYCHIC = 0x2000n as RibbonFlag; /** Ribbon for winning the ice monotype challenge */ - public static readonly MONO_ICE = 0x4000 as RibbonFlag; + public static readonly MONO_ICE = 0x4000n as RibbonFlag; /** Ribbon for winning the dragon monotype challenge */ - public static readonly MONO_DRAGON = 0x8000 as RibbonFlag; + public static readonly MONO_DRAGON = 0x8000n as RibbonFlag; /** Ribbon for winning the dark monotype challenge */ - public static readonly MONO_DARK = 0x10000 as RibbonFlag; + public static readonly MONO_DARK = 0x10000n as RibbonFlag; /** Ribbon for winning the fairy monotype challenge */ - public static readonly MONO_FAIRY = 0x20000 as RibbonFlag; + public static readonly MONO_FAIRY = 0x20000n as RibbonFlag; //#endregion Monotype ribbons //#region Monogen ribbons /** Ribbon for winning the the mono gen 1 challenge */ - public static readonly MONO_GEN_1 = 0x40000 as RibbonFlag; + public static readonly MONO_GEN_1 = 0x40000n as RibbonFlag; /** Ribbon for winning the the mono gen 2 challenge */ - public static readonly MONO_GEN_2 = 0x80000 as RibbonFlag; + public static readonly MONO_GEN_2 = 0x80000n as RibbonFlag; /** Ribbon for winning the mono gen 3 challenge */ - public static readonly MONO_GEN_3 = 0x100000 as RibbonFlag; + public static readonly MONO_GEN_3 = 0x100000n as RibbonFlag; /** Ribbon for winning the mono gen 4 challenge */ - public static readonly MONO_GEN_4 = 0x200000 as RibbonFlag; + public static readonly MONO_GEN_4 = 0x200000n as RibbonFlag; /** Ribbon for winning the mono gen 5 challenge */ - public static readonly MONO_GEN_5 = 0x400000 as RibbonFlag; + public static readonly MONO_GEN_5 = 0x400000n as RibbonFlag; /** Ribbon for winning the mono gen 6 challenge */ - public static readonly MONO_GEN_6 = 0x800000 as RibbonFlag; + public static readonly MONO_GEN_6 = 0x800000n as RibbonFlag; /** Ribbon for winning the mono gen 7 challenge */ - public static readonly MONO_GEN_7 = 0x1000000 as RibbonFlag; + public static readonly MONO_GEN_7 = 0x1000000n as RibbonFlag; /** Ribbon for winning the mono gen 8 challenge */ - public static readonly MONO_GEN_8 = 0x2000000 as RibbonFlag; + public static readonly MONO_GEN_8 = 0x2000000n as RibbonFlag; /** Ribbon for winning the mono gen 9 challenge */ - public static readonly MONO_GEN_9 = 0x4000000 as RibbonFlag; + public static readonly MONO_GEN_9 = 0x4000000n as RibbonFlag; //#endregion Monogen ribbons /** Ribbon for winning classic */ - public static readonly CLASSIC = 0x8000000 as RibbonFlag; + public static readonly CLASSIC = 0x8000000n as RibbonFlag; /** Ribbon for winning the nuzzlocke challenge */ - public static readonly NUZLOCKE = 0x10000000 as RibbonFlag; + public static readonly NUZLOCKE = 0x10000000n as RibbonFlag; /** Ribbon for reaching max friendship */ - public static readonly FRIENDSHIP = 0x20000000 as RibbonFlag; + public static readonly FRIENDSHIP = 0x20000000n as RibbonFlag; /** Ribbon for winning the flip stats challenge */ - public static readonly FLIP_STATS = 0x40000000 as RibbonFlag; + public static readonly FLIP_STATS = 0x40000000n as RibbonFlag; /** Ribbon for winning the inverse challenge */ - public static readonly INVERSE = 0x80000000 as RibbonFlag; + public static readonly INVERSE = 0x80000000n as RibbonFlag; /** Ribbon for winning the fresh start challenge */ - public static readonly FRESH_START = 0x100000000 as RibbonFlag; + public static readonly FRESH_START = 0x100000000n as RibbonFlag; /** Ribbon for winning the hardcore challenge */ - public static readonly HARDCORE = 0x200000000 as RibbonFlag; + public static readonly HARDCORE = 0x200000000n as RibbonFlag; /** Ribbon for winning the limited catch challenge */ - public static readonly LIMITED_CATCH = 0x400000000 as RibbonFlag; + public static readonly LIMITED_CATCH = 0x400000000n as RibbonFlag; /** Ribbon for winning the limited support challenge set to no heal */ - public static readonly NO_HEAL = 0x800000000 as RibbonFlag; + public static readonly NO_HEAL = 0x800000000n as RibbonFlag; /** Ribbon for winning the limited uspport challenge set to no shop */ - public static readonly NO_SHOP = 0x1000000000 as RibbonFlag; + public static readonly NO_SHOP = 0x1000000000n as RibbonFlag; /** Ribbon for winning the limited support challenge set to both*/ - public static readonly NO_SUPPORT = 0x2000000000 as RibbonFlag; + public static readonly NO_SUPPORT = 0x2000000000n as RibbonFlag; // NOTE: max possible ribbon flag is 0x20000000000000 (53 total ribbons) // Once this is exceeded, bitfield needs to be changed to a bigint or even a uint array @@ -104,7 +104,7 @@ export class RibbonData { /** Create a new instance of RibbonData. Generally, {@linkcode fromJSON} is used instead. */ constructor(value: number) { - this.payload = value; + this.payload = BigInt(value); } /** Serialize the bitfield payload as a hex encoded string */ diff --git a/src/system/ribbons/ribbon-methods.ts b/src/system/ribbons/ribbon-methods.ts index a465357ab8c..138c0be7b51 100644 --- a/src/system/ribbons/ribbon-methods.ts +++ b/src/system/ribbons/ribbon-methods.ts @@ -15,6 +15,6 @@ export function awardRibbonsToSpeciesLine(id: SpeciesId, ribbons: RibbonFlag): v dexData[id].ribbons.award(ribbons); // Mark all pre-evolutions of the Pokémon with the same ribbon flags. for (let prevoId = pokemonPrevolutions[id]; !isNullOrUndefined(prevoId); prevoId = pokemonPrevolutions[prevoId]) { - dexData[id].ribbons.award(ribbons); + dexData[prevoId].ribbons.award(ribbons); } } diff --git a/src/system/settings/settings.ts b/src/system/settings/settings.ts index 32d9e0ee2be..86305b3f7ed 100644 --- a/src/system/settings/settings.ts +++ b/src/system/settings/settings.ts @@ -197,35 +197,35 @@ export const Setting: Array = [ options: [ { value: "1", - label: i18next.t("settings:gameSpeed1x"), + label: i18next.t("settings:gameSpeed100x"), }, { value: "1.25", - label: i18next.t("settings:gameSpeed1_25x"), + label: i18next.t("settings:gameSpeed125x"), }, { value: "1.5", - label: i18next.t("settings:gameSpeed1_5x"), + label: i18next.t("settings:gameSpeed150x"), }, { value: "2", - label: i18next.t("settings:gameSpeed2x"), + label: i18next.t("settings:gameSpeed200x"), }, { value: "2.5", - label: i18next.t("settings:gameSpeed2_5x"), + label: i18next.t("settings:gameSpeed250x"), }, { value: "3", - label: i18next.t("settings:gameSpeed3x"), + label: i18next.t("settings:gameSpeed300x"), }, { value: "4", - label: i18next.t("settings:gameSpeed4x"), + label: i18next.t("settings:gameSpeed400x"), }, { value: "5", - label: i18next.t("settings:gameSpeed5x"), + label: i18next.t("settings:gameSpeed500x"), }, ], default: 3, @@ -566,7 +566,7 @@ export const Setting: Array = [ }, { value: "Back", - label: i18next.t("settings:timeOfDay_back"), + label: i18next.t("settings:timeOfDayBack"), }, ], default: 0, diff --git a/src/ui/achvs-ui-handler.ts b/src/ui/achvs-ui-handler.ts index 2c04e24e0f2..b0f49d13c86 100644 --- a/src/ui/achvs-ui-handler.ts +++ b/src/ui/achvs-ui-handler.ts @@ -30,7 +30,7 @@ const languageSettings: { [key: string]: LanguageSetting } = { export class AchvsUiHandler extends MessageUiHandler { private readonly ROWS = 4; - private readonly COLS = 17; + private readonly COLS = 18; private mainContainer: Phaser.GameObjects.Container; private iconsContainer: Phaser.GameObjects.Container; @@ -96,7 +96,7 @@ export class AchvsUiHandler extends MessageUiHandler { const genderIndex = globalScene.gameData.gender ?? PlayerGender.MALE; const genderStr = PlayerGender[genderIndex].toLowerCase(); - this.achvsName = i18next.t("achv:Achievements.name", { context: genderStr }); + this.achvsName = i18next.t("achv:achievements.name", { context: genderStr }); this.vouchersName = i18next.t("voucher:vouchers"); this.iconsBg = addWindow(0, this.headerBg.height, WIDTH - 2, HEIGHT - this.headerBg.height - 68).setOrigin(0); @@ -115,8 +115,8 @@ export class AchvsUiHandler extends MessageUiHandler { this.icons = []; for (let a = 0; a < this.ROWS * this.COLS; a++) { - const x = (a % this.COLS) * 18; - const y = Math.floor(a / this.COLS) * 18; + const x = (a % this.COLS) * 17; + const y = Math.floor(a / this.COLS) * 19; const icon = globalScene.add.sprite(x, y, "items", "unknown").setOrigin(0).setScale(0.5); @@ -214,7 +214,7 @@ export class AchvsUiHandler extends MessageUiHandler { this.showText(!hidden ? achv.description : ""); this.scoreText.setText(`${achv.score}pt`); this.unlockText.setText( - unlocked ? new Date(achvUnlocks[achv.id]).toLocaleDateString() : i18next.t("achv:Locked.name"), + unlocked ? new Date(achvUnlocks[achv.id]).toLocaleDateString() : i18next.t("achv:locked.name"), ); } diff --git a/src/ui/arena-flyout.ts b/src/ui/arena-flyout.ts index e243bef342e..da062f5c96f 100644 --- a/src/ui/arena-flyout.ts +++ b/src/ui/arena-flyout.ts @@ -1,5 +1,5 @@ import { globalScene } from "#app/global-scene"; -import { ArenaTrapTag } from "#data/arena-tag"; +import { EntryHazardTag } from "#data/arena-tag"; import { TerrainType } from "#data/terrain"; import { ArenaTagSide } from "#enums/arena-tag-side"; import { ArenaTagType } from "#enums/arena-tag-type"; @@ -287,7 +287,7 @@ export class ArenaFlyout extends Phaser.GameObjects.Container { switch (arenaEffectChangedEvent.constructor) { case TagAddedEvent: { const tagAddedEvent = arenaEffectChangedEvent as TagAddedEvent; - const isArenaTrapTag = globalScene.arena.getTag(tagAddedEvent.arenaTagType) instanceof ArenaTrapTag; + const isArenaTrapTag = globalScene.arena.getTag(tagAddedEvent.arenaTagType) instanceof EntryHazardTag; let arenaEffectType: ArenaEffectType; if (tagAddedEvent.arenaTagSide === ArenaTagSide.BOTH) { diff --git a/src/ui/base-stats-overlay.ts b/src/ui/base-stats-overlay.ts index 3b432e13096..b3cccf34298 100644 --- a/src/ui/base-stats-overlay.ts +++ b/src/ui/base-stats-overlay.ts @@ -4,6 +4,7 @@ import { TextStyle } from "#enums/text-style"; import { addTextObject } from "#ui/text"; import { addWindow } from "#ui/ui-theme"; import { fixedInt } from "#utils/common"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; interface BaseStatsOverlaySettings { @@ -68,7 +69,9 @@ export class BaseStatsOverlay extends Phaser.GameObjects.Container implements In // show this component with infos for the specific move show(values: number[], total: number): boolean { for (let i = 0; i < 6; i++) { - this.statsLabels[i].setText(i18next.t(`pokemonInfo:Stat.${shortStats[i]}shortened`) + ": " + `${values[i]}`); + this.statsLabels[i].setText( + i18next.t(`pokemonInfo:stat.${toCamelCase(shortStats[i])}Shortened`) + ": " + `${values[i]}`, + ); // This accounts for base stats up to 200, might not be enough. // TODO: change color based on value. this.statsShadows[i].setSize(values[i] / 2, 5); diff --git a/src/ui/battle-info/battle-info.ts b/src/ui/battle-info/battle-info.ts index 0aedfbdf5e7..810d0c7c328 100644 --- a/src/ui/battle-info/battle-info.ts +++ b/src/ui/battle-info/battle-info.ts @@ -9,6 +9,7 @@ import type { Pokemon } from "#field/pokemon"; import { getVariantTint } from "#sprites/variant"; import { addTextObject } from "#ui/text"; import { fixedInt, getLocalizedSpriteKey, getShinyDescriptor } from "#utils/common"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; /** @@ -361,7 +362,7 @@ export abstract class BattleInfo extends Phaser.GameObjects.Container { globalScene.ui.showTooltip( "", i18next.t("fightUiHandler:teraHover", { - type: i18next.t(`pokemonInfo:Type.${PokemonType[this.lastTeraType]}`), + type: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[this.lastTeraType])}`), }), ); } diff --git a/src/ui/bgm-bar.ts b/src/ui/bgm-bar.ts index e2c6925ec30..f24f372a804 100644 --- a/src/ui/bgm-bar.ts +++ b/src/ui/bgm-bar.ts @@ -1,7 +1,7 @@ import { globalScene } from "#app/global-scene"; import { TextStyle } from "#enums/text-style"; import { addTextObject } from "#ui/text"; -import { toTitleCase } from "#utils/strings"; +import { toCamelCase, toTitleCase } from "#utils/strings"; import i18next from "i18next"; const hiddenX = -150; @@ -100,7 +100,7 @@ export class BgmBar extends Phaser.GameObjects.Container { } getRealBgmName(bgmName: string): string { - return i18next.t([`bgmName:${bgmName}`, "bgmName:missing_entries"], { + return i18next.t([`bgmName:${toCamelCase(bgmName)}`, "bgmName:missingEntries"], { name: toTitleCase(bgmName), }); } diff --git a/src/ui/confirm-ui-handler.ts b/src/ui/confirm-ui-handler.ts index 49e88556f1b..529d1bd8bbb 100644 --- a/src/ui/confirm-ui-handler.ts +++ b/src/ui/confirm-ui-handler.ts @@ -31,14 +31,14 @@ export class ConfirmUiHandler extends AbstractOptionSelectUiHandler { const config: OptionSelectConfig = { options: [ { - label: i18next.t("partyUiHandler:SUMMARY"), + label: i18next.t("partyUiHandler:summary"), handler: () => { args[0](); return true; }, }, { - label: i18next.t("partyUiHandler:POKEDEX"), + label: i18next.t("partyUiHandler:pokedex"), handler: () => { args[1](); return true; diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index 0287e0ee7a5..e54ee445aee 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -743,7 +743,7 @@ export class EggGachaUiHandler extends MessageUiHandler { if (!freePulls && globalScene.gameData.eggs.length + pulls > 99) { errorKey = "egg:tooManyEggs"; - } else if (!freePulls && !globalScene.gameData.voucherCounts[voucherType]) { + } else if (!freePulls && globalScene.gameData.voucherCounts[voucherType] < vouchersConsumed) { errorKey = "egg:notEnoughVouchers"; } diff --git a/src/ui/game-stats-ui-handler.ts b/src/ui/game-stats-ui-handler.ts index ed66230bed7..be41e4d21b9 100644 --- a/src/ui/game-stats-ui-handler.ts +++ b/src/ui/game-stats-ui-handler.ts @@ -1,7 +1,9 @@ +import { loggedInUser } from "#app/account"; import { globalScene } from "#app/global-scene"; import { speciesStarterCosts } from "#balance/starters"; import { Button } from "#enums/buttons"; import { DexAttr } from "#enums/dex-attr"; +import { PlayerGender } from "#enums/player-gender"; import { TextStyle } from "#enums/text-style"; import { UiTheme } from "#enums/ui-theme"; import type { GameData } from "#system/game-data"; @@ -46,10 +48,17 @@ const displayStats: DisplayStats = { return `${starterCount} (${Math.floor((starterCount / Object.keys(speciesStarterCosts).length) * 1000) / 10}%)`; }, }, + dexEncountered: { + label_key: "speciesEncountered", + sourceFunc: gameData => { + const seenCount = gameData.getSpeciesCount(d => !!d.seenCount); + return `${seenCount} (${Math.floor((seenCount / Object.keys(gameData.dexData).length) * 1000) / 10}%)`; + }, + }, dexSeen: { label_key: "speciesSeen", sourceFunc: gameData => { - const seenCount = gameData.getSpeciesCount(d => !!d.seenAttr); + const seenCount = gameData.getSpeciesCount(d => !!d.seenAttr || !!d.caughtAttr); return `${seenCount} (${Math.floor((seenCount / Object.keys(gameData.dexData).length) * 1000) / 10}%)`; }, }, @@ -227,6 +236,9 @@ export class GameStatsUiHandler extends UiHandler { private arrowUp: Phaser.GameObjects.Sprite; private arrowDown: Phaser.GameObjects.Sprite; + /** Logged in username */ + private headerText: Phaser.GameObjects.Text; + /** Whether the UI is single column mode */ private get singleCol(): boolean { const resolvedLang = i18next.resolvedLanguage ?? "en"; @@ -296,6 +308,23 @@ export class GameStatsUiHandler extends UiHandler { return GameStatsUiHandler.ROWS_PER_PAGE * this.columnCount; } + /** + * Returns the username of logged in user. If the username is hidden, the trainer name based on gender will be displayed. + * @returns The username of logged in user + */ + private getUsername(): string { + const usernameReplacement = + globalScene.gameData.gender === PlayerGender.FEMALE + ? i18next.t("trainerNames:playerF") + : i18next.t("trainerNames:playerM"); + + const displayName = !globalScene.hideUsername + ? (loggedInUser?.username ?? i18next.t("common:guest")) + : usernameReplacement; + + return i18next.t("gameStatsUiHandler:stats", { username: displayName }); + } + // #endregion Columnar-specific properties setup() { @@ -316,11 +345,11 @@ export class GameStatsUiHandler extends UiHandler { const headerBg = addWindow(0, 0, sWidth - 2, 24).setOrigin(0); - const headerText = addTextObject(0, 0, i18next.t("gameStatsUiHandler:stats"), TextStyle.HEADER_LABEL) + this.headerText = addTextObject(0, 0, this.getUsername(), TextStyle.HEADER_LABEL) .setOrigin(0) .setPositionRelative(headerBg, 8, 4); - this.gameStatsContainer.add([headerBg, headerText]); + this.gameStatsContainer.add([headerBg, this.headerText]); const colWidth = this.colWidth; @@ -368,6 +397,10 @@ export class GameStatsUiHandler extends UiHandler { show(args: any[]): boolean { super.show(args); + + // show updated username on every render + this.headerText.setText(this.getUsername()); + this.gameStatsContainer.setActive(true).setVisible(true); this.arrowUp.setActive(true).play("prompt").setVisible(false); diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index da6bc9ced78..4f6d6ede488 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -17,6 +17,7 @@ import { addWindow, WindowVariant } from "#ui/ui-theme"; import { fixedInt, isLocal, sessionIdKey } from "#utils/common"; import { getCookie } from "#utils/cookies"; import { getEnumValues } from "#utils/enums"; +import { toCamelCase } from "#utils/strings"; import { isBeta } from "#utils/utility-vars"; import i18next from "i18next"; @@ -138,7 +139,7 @@ export class MenuUiHandler extends MessageUiHandler { this.optionSelectText = addTextObject( 0, 0, - this.menuOptions.map(o => `${i18next.t(`menuUiHandler:${MenuOptions[o]}`)}`).join("\n"), + this.menuOptions.map(o => `${i18next.t(`menuUiHandler:${toCamelCase(MenuOptions[o])}`)}`).join("\n"), TextStyle.WINDOW, { maxLines: this.menuOptions.length }, ); diff --git a/src/ui/mystery-encounter-ui-handler.ts b/src/ui/mystery-encounter-ui-handler.ts index 881c375fa8a..37f77cf43b9 100644 --- a/src/ui/mystery-encounter-ui-handler.ts +++ b/src/ui/mystery-encounter-ui-handler.ts @@ -473,7 +473,7 @@ export class MysteryEncounterUiHandler extends UiHandler { const viewPartyText = addBBCodeTextObject( globalScene.scaledCanvas.width, -24, - getBBCodeFrag(i18next.t("mysteryEncounterMessages:view_party_button"), TextStyle.PARTY), + getBBCodeFrag(i18next.t("mysteryEncounterMessages:viewPartyButton"), TextStyle.PARTY), TextStyle.PARTY, ); this.optionsContainer.add(viewPartyText); @@ -694,7 +694,7 @@ export class MysteryEncounterUiHandler extends UiHandler { duration: 750, onComplete: () => { this.dexProgressContainer.on("pointerover", () => { - globalScene.ui.showTooltip("", i18next.t("mysteryEncounterMessages:affects_pokedex"), true); + globalScene.ui.showTooltip("", i18next.t("mysteryEncounterMessages:affectsPokedex"), true); }); this.dexProgressContainer.on("pointerout", () => { globalScene.ui.hideTooltip(); diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index 3101f46f098..d3c67f66ec9 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -6,6 +6,7 @@ import { SpeciesFormChangeItemTrigger } from "#data/form-change-triggers"; import { Gender, getGenderColor, getGenderSymbol } from "#data/gender"; import { Button } from "#enums/buttons"; import { ChallengeType } from "#enums/challenge-type"; +import { Challenges } from "#enums/challenges"; import { Command } from "#enums/command"; import { FormChangeItem } from "#enums/form-change-item"; import { MoveId } from "#enums/move-id"; @@ -27,7 +28,7 @@ import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text"; import { addWindow } from "#ui/ui-theme"; import { applyChallenges } from "#utils/challenge-utils"; import { BooleanHolder, getLocalizedSpriteKey, randInt } from "#utils/common"; -import { toTitleCase } from "#utils/strings"; +import { toCamelCase, toTitleCase } from "#utils/strings"; import i18next from "i18next"; import type BBCodeText from "phaser3-rex-plugins/plugins/bbcodetext"; @@ -1427,6 +1428,11 @@ export class PartyUiHandler extends MessageUiHandler { this.eraseOptionsCursor(); } + if (pokemon.isFainted() && globalScene.gameMode.hasChallenge(Challenges.HARDCORE)) { + this.updateOptionsHardcore(); + return; + } + switch (this.partyUiMode) { case PartyUiMode.MOVE_MODIFIER: this.updateOptionsWithMoveModifierMode(pokemon); @@ -1526,6 +1532,34 @@ export class PartyUiHandler extends MessageUiHandler { this.updateOptionsWindow(); } + updateOptionsHardcore(): void { + const pokemon = globalScene.getPlayerParty()[this.cursor]; + + switch (this.partyUiMode) { + case PartyUiMode.MODIFIER_TRANSFER: + if (!this.transferMode) { + this.updateOptionsWithModifierTransferMode(pokemon); + } else { + this.options.push(PartyOption.TRANSFER); + this.addCommonOptions(pokemon); + } + break; + case PartyUiMode.DISCARD: + this.updateOptionsWithModifierTransferMode(pokemon); + break; + case PartyUiMode.SWITCH: + this.options.push(PartyOption.RELEASE); + break; + case PartyUiMode.RELEASE: + this.options.push(PartyOption.RELEASE); + break; + } + + // Generic, these are applied to all Modes + this.addCancelAndScrollOptions(); + this.updateOptionsWindow(); + } + private updateOptionsWindow(): void { const pokemon = globalScene.getPlayerParty()[this.cursor]; @@ -1573,12 +1607,12 @@ export class PartyUiHandler extends MessageUiHandler { const formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon); 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}`; + 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")}`; + optionName = `${pokemon.pauseEvolutions ? i18next.t("partyUiHandler:unpausedEvolution") : i18next.t("partyUiHandler:pauseEvolution")}`; } else { if (this.localizedOptions.includes(option)) { - optionName = i18next.t(`partyUiHandler:${PartyOption[option]}`); + optionName = i18next.t(`partyUiHandler:${toCamelCase(PartyOption[option])}`); } else { optionName = toTitleCase(PartyOption[option]); } @@ -1595,7 +1629,7 @@ export class PartyUiHandler extends MessageUiHandler { .getLevelMoves() .find(plm => plm[1] === move); } else if (option === PartyOption.ALL) { - optionName = i18next.t("partyUiHandler:ALL"); + optionName = i18next.t("partyUiHandler:all"); } else { const itemModifiers = this.getItemModifiers(pokemon); const itemModifier = itemModifiers[option]; @@ -2190,7 +2224,7 @@ class PartyDiscardModeButton extends Phaser.GameObjects.Container { setup(party: PartyUiHandler) { this.transferIcon = globalScene.add.sprite(0, 0, "party_transfer"); this.discardIcon = globalScene.add.sprite(0, 0, "party_discard"); - this.textBox = addTextObject(-8, -7, i18next.t("partyUiHandler:TRANSFER"), TextStyle.PARTY); + this.textBox = addTextObject(-8, -7, i18next.t("partyUiHandler:transfer"), TextStyle.PARTY); this.party = party; this.add(this.transferIcon); @@ -2238,14 +2272,14 @@ class PartyDiscardModeButton extends Phaser.GameObjects.Container { this.transferIcon.setVisible(true); this.discardIcon.setVisible(false); this.textBox.setVisible(true); - this.textBox.setText(i18next.t("partyUiHandler:TRANSFER")); + this.textBox.setText(i18next.t("partyUiHandler:transfer")); this.transferIcon.displayWidth = this.textBox.text.length * 9 + 3; break; case PartyUiMode.DISCARD: this.transferIcon.setVisible(false); this.discardIcon.setVisible(true); this.textBox.setVisible(true); - this.textBox.setText(i18next.t("partyUiHandler:DISCARD")); + this.textBox.setText(i18next.t("partyUiHandler:discard")); this.discardIcon.displayWidth = this.textBox.text.length * 9 + 3; break; } diff --git a/src/ui/pokedex-mon-container.ts b/src/ui/pokedex-mon-container.ts index 832d7e4bcd6..15ef6c9b5c8 100644 --- a/src/ui/pokedex-mon-container.ts +++ b/src/ui/pokedex-mon-container.ts @@ -107,9 +107,9 @@ export class PokedexMonContainer extends Phaser.GameObjects.Container { this.candyUpgradeOverlayIcon = candyUpgradeOverlayIcon; // move icons - const eggMove1Icon = globalScene.add.image(0, 12, "mystery_egg"); - eggMove1Icon.setOrigin(0, 0); - eggMove1Icon.setScale(0.25); + const eggMove1Icon = globalScene.add.image(0, 12, "common_egg"); + eggMove1Icon.setOrigin(0, -0.03); + eggMove1Icon.setScale(0.24); eggMove1Icon.setVisible(false); this.add(eggMove1Icon); this.eggMove1Icon = eggMove1Icon; @@ -123,7 +123,7 @@ export class PokedexMonContainer extends Phaser.GameObjects.Container { this.tmMove1Icon = tmMove1Icon; // move icons - const eggMove2Icon = globalScene.add.image(7, 12, "mystery_egg"); + const eggMove2Icon = globalScene.add.image(7, 12, "common_egg"); eggMove2Icon.setOrigin(0, 0); eggMove2Icon.setScale(0.25); eggMove2Icon.setVisible(false); diff --git a/src/ui/pokedex-page-ui-handler.ts b/src/ui/pokedex-page-ui-handler.ts index 49658d9cfc9..706f139b8bb 100644 --- a/src/ui/pokedex-page-ui-handler.ts +++ b/src/ui/pokedex-page-ui-handler.ts @@ -57,7 +57,7 @@ import { addWindow } from "#ui/ui-theme"; import { BooleanHolder, getLocalizedSpriteKey, isNullOrUndefined, padInt, rgbHexToRgba } from "#utils/common"; import { getEnumValues } from "#utils/enums"; import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils"; -import { toTitleCase } from "#utils/strings"; +import { toCamelCase, toTitleCase } from "#utils/strings"; import { argbFromRgba } from "@material/material-color-utilities"; import i18next from "i18next"; import type BBCodeText from "phaser3-rex-plugins/plugins/gameobjects/tagtext/bbcodetext/BBCodeText"; @@ -640,7 +640,7 @@ export class PokedexPageUiHandler extends MessageUiHandler { this.optionSelectText = addBBCodeTextObject( 0, 0, - this.menuOptions.map(o => `${i18next.t(`pokedexUiHandler:${MenuOptions[o]}`)}`).join("\n"), + this.menuOptions.map(o => `${i18next.t(`pokedexUiHandler:${toCamelCase(`menu${MenuOptions[o]}`)}`)}`).join("\n"), TextStyle.WINDOW, { maxLines: this.menuOptions.length, lineSpacing: 12 }, ); @@ -757,7 +757,7 @@ export class PokedexPageUiHandler extends MessageUiHandler { return this.menuOptions .map(o => { - const label = `${i18next.t(`pokedexUiHandler:${MenuOptions[o]}`)}`; + const label = i18next.t(`pokedexUiHandler:${toCamelCase(`menu${MenuOptions[o]}`)}`); const isDark = !isSeen || (!isStarterCaught && (o === MenuOptions.TOGGLE_IVS || o === MenuOptions.NATURES)) || @@ -1517,13 +1517,13 @@ export class PokedexPageUiHandler extends MessageUiHandler { this.biomes.map(b => { options.push({ label: - i18next.t(`biome:${BiomeId[b.biome].toUpperCase()}`) + + i18next.t(`biome:${toCamelCase(BiomeId[b.biome])}`) + " - " + - i18next.t(`biome:${BiomePoolTier[b.tier].toUpperCase()}`) + + i18next.t(`biome:${toCamelCase(BiomePoolTier[b.tier])}`) + (b.tod.length === 1 && b.tod[0] === -1 ? "" : " (" + - b.tod.map(tod => i18next.t(`biome:${TimeOfDay[tod].toUpperCase()}`)).join(", ") + + b.tod.map(tod => i18next.t(`biome:${toCamelCase(TimeOfDay[tod])}`)).join(", ") + ")"), handler: () => false, }); @@ -1538,13 +1538,13 @@ export class PokedexPageUiHandler extends MessageUiHandler { this.preBiomes.map(b => { options.push({ label: - i18next.t(`biome:${BiomeId[b.biome].toUpperCase()}`) + + i18next.t(`biome:${toCamelCase(BiomeId[b.biome])}`) + " - " + - i18next.t(`biome:${BiomePoolTier[b.tier].toUpperCase()}`) + + i18next.t(`biome:${toCamelCase(BiomePoolTier[b.tier])}`) + (b.tod.length === 1 && b.tod[0] === -1 ? "" : " (" + - b.tod.map(tod => i18next.t(`biome:${TimeOfDay[tod].toUpperCase()}`)).join(", ") + + b.tod.map(tod => i18next.t(`biome:${toCamelCase(TimeOfDay[tod])}`)).join(", ") + ")"), handler: () => false, }); @@ -1777,7 +1777,9 @@ export class PokedexPageUiHandler extends MessageUiHandler { this.blockInput = true; ui.setMode(UiMode.POKEDEX_PAGE, "refresh").then(() => { ui.showText(i18next.t("pokedexUiHandler:showNature"), null, () => { - const natures = globalScene.gameData.getNaturesForAttr(this.speciesStarterDexEntry?.natureAttr); + const starterDexEntry = + globalScene.gameData.dexData[this.getStarterSpeciesId(this.species.speciesId)]; + const natures = globalScene.gameData.getNaturesForAttr(starterDexEntry.natureAttr); ui.setModeWithoutClear(UiMode.OPTION_SELECT, { options: natures .map((n: Nature, _i: number) => { @@ -2612,7 +2614,7 @@ export class PokedexPageUiHandler extends MessageUiHandler { // Setting growth rate text if (isFormCaught) { let growthReadable = toTitleCase(GrowthRate[species.growthRate]); - const growthAux = growthReadable.replace(" ", "_"); + const growthAux = toCamelCase(growthReadable); if (i18next.exists("growth:" + growthAux)) { growthReadable = i18next.t(("growth:" + growthAux) as any); } @@ -2829,7 +2831,8 @@ export class PokedexPageUiHandler extends MessageUiHandler { this.statsContainer.setVisible(true); - this.statsContainer.updateIvs(this.speciesStarterDexEntry.ivs); + const ivs = globalScene.gameData.dexData[this.getStarterSpeciesId(this.species.speciesId)].ivs; + this.statsContainer.updateIvs(ivs); } clearText() { diff --git a/src/ui/pokedex-ui-handler.ts b/src/ui/pokedex-ui-handler.ts index 6a6afea9798..01046bfef9c 100644 --- a/src/ui/pokedex-ui-handler.ts +++ b/src/ui/pokedex-ui-handler.ts @@ -47,6 +47,7 @@ import { BooleanHolder, fixedInt, getLocalizedSpriteKey, padInt, randIntRange, r import type { StarterPreferences } from "#utils/data"; import { loadStarterPreferences } from "#utils/data"; import { getPokemonSpeciesForm, getPokerusStarters } from "#utils/pokemon-utils"; +import { toCamelCase } from "#utils/strings"; import { argbFromRgba } from "@material/material-color-utilities"; import i18next from "i18next"; @@ -324,7 +325,7 @@ export class PokedexUiHandler extends MessageUiHandler { .filter(value => typeof value === "number") // Filter numeric values from the enum .map( (biomeValue, index) => - new DropDownOption(index, new DropDownLabel(i18next.t(`biome:${BiomeId[biomeValue].toUpperCase()}`))), + new DropDownOption(index, new DropDownLabel(i18next.t(`biome:${toCamelCase(BiomeId[biomeValue])}`))), ); biomeOptions.push(new DropDownOption(biomeOptions.length, new DropDownLabel(i18next.t("filterBar:uncatchable")))); const biomeDropDown: DropDown = new DropDown(0, 0, biomeOptions, this.updateStarters, DropDownType.HYBRID); @@ -415,6 +416,11 @@ export class PokedexUiHandler extends MessageUiHandler { new DropDownLabel(i18next.t("filterBar:isSeen"), undefined, DropDownState.ON), new DropDownLabel(i18next.t("filterBar:isUnseen"), undefined, DropDownState.EXCLUDE), ]; + const encounteredSpeciesLabels = [ + new DropDownLabel(i18next.t("filterBar:encounteredSpecies"), undefined, DropDownState.OFF), + new DropDownLabel(i18next.t("filterBar:isEncountered"), undefined, DropDownState.ON), + new DropDownLabel(i18next.t("filterBar:isNotEncountered"), undefined, DropDownState.EXCLUDE), + ]; const eggLabels = [ new DropDownLabel(i18next.t("filterBar:egg"), undefined, DropDownState.OFF), new DropDownLabel(i18next.t("filterBar:eggPurchasable"), undefined, DropDownState.ON), @@ -429,6 +435,7 @@ export class PokedexUiHandler extends MessageUiHandler { new DropDownOption("WIN", winLabels), new DropDownOption("HIDDEN_ABILITY", hiddenAbilityLabels), new DropDownOption("SEEN_SPECIES", seenSpeciesLabels), + new DropDownOption("ENCOUNTERED_SPECIES", encounteredSpeciesLabels), new DropDownOption("EGG", eggLabels), new DropDownOption("POKERUS", pokerusLabels), ]; @@ -809,6 +816,10 @@ export class PokedexUiHandler extends MessageUiHandler { return false; } + isEncountered(_species: PokemonSpecies, dexEntry: DexEntry, _seenFilter?: boolean): boolean { + return !!dexEntry.seenCount; + } + /** * Determines if 'Icon' based upgrade notifications should be shown * @returns true if upgrade notifications are enabled and set to display an 'Icon' @@ -1627,7 +1638,7 @@ export class PokedexUiHandler extends MessageUiHandler { // Seen Filter const dexEntry = globalScene.gameData.dexData[species.speciesId]; - const isItSeen = this.isSeen(species, dexEntry, true); + const isItSeen = this.isSeen(species, dexEntry, true) || !!dexEntry.caughtAttr; const fitsSeen = this.filterBar.getVals(DropDownColumn.MISC).some(misc => { if (misc.val === "SEEN_SPECIES" && misc.state === DropDownState.ON) { return isItSeen; @@ -1640,6 +1651,20 @@ export class PokedexUiHandler extends MessageUiHandler { } }); + // Encountered Filter + const isItEncountered = this.isEncountered(species, dexEntry, true); + const fitsEncountered = this.filterBar.getVals(DropDownColumn.MISC).some(misc => { + if (misc.val === "ENCOUNTERED_SPECIES" && misc.state === DropDownState.ON) { + return isItEncountered; + } + if (misc.val === "ENCOUNTERED_SPECIES" && misc.state === DropDownState.EXCLUDE) { + return !isItEncountered; + } + if (misc.val === "ENCOUNTERED_SPECIES" && misc.state === DropDownState.OFF) { + return true; + } + }); + // Egg Purchasable Filter const isEggPurchasable = this.isSameSpeciesEggAvailable(species.speciesId); const fitsEgg = this.filterBar.getVals(DropDownColumn.MISC).some(misc => { @@ -1682,6 +1707,7 @@ export class PokedexUiHandler extends MessageUiHandler { fitsWin && fitsHA && fitsSeen && + fitsEncountered && fitsEgg && fitsPokerus ) { diff --git a/src/ui/rename-run-ui-handler.ts b/src/ui/rename-run-ui-handler.ts index 23ba0137f2d..a94b7b08fb9 100644 --- a/src/ui/rename-run-ui-handler.ts +++ b/src/ui/rename-run-ui-handler.ts @@ -5,7 +5,7 @@ import type { ModalConfig } from "./modal-ui-handler"; export class RenameRunFormUiHandler extends FormModalUiHandler { getModalTitle(_config?: ModalConfig): string { - return i18next.t("menu:renamerun"); + return i18next.t("menu:renameRun"); } getWidth(_config?: ModalConfig): number { diff --git a/src/ui/run-history-ui-handler.ts b/src/ui/run-history-ui-handler.ts index 457c48654a3..6f4d9024832 100644 --- a/src/ui/run-history-ui-handler.ts +++ b/src/ui/run-history-ui-handler.ts @@ -337,7 +337,7 @@ class RunEntryContainer extends Phaser.GameObjects.Container { // Because of the interesting mechanics behind rival names, the rival name and title have to be retrieved differently const RIVAL_TRAINER_ID_THRESHOLD = 375; if (data.trainer.trainerType >= RIVAL_TRAINER_ID_THRESHOLD) { - const rivalName = tObj.variant === TrainerVariant.FEMALE ? "trainerNames:rival_female" : "trainerNames:rival"; + const rivalName = tObj.variant === TrainerVariant.FEMALE ? "trainerNames:rivalFemale" : "trainerNames:rival"; const gameOutcomeLabel = addTextObject( 8, 5, diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index db0790275fc..5fc0f37c72d 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -337,7 +337,7 @@ export class RunInfoUiHandler extends UiHandler { if (this.runInfo.trainer.trainerType >= RIVAL_TRAINER_ID_THRESHOLD) { trainerName = trainerObj.variant === TrainerVariant.FEMALE - ? i18next.t("trainerNames:rival_female") + ? i18next.t("trainerNames:rivalFemale") : i18next.t("trainerNames:rival"); } else { trainerName = trainerObj.getName(0, true); @@ -700,7 +700,11 @@ export class RunInfoUiHandler extends UiHandler { const typeTextColor = `[color=${TypeColor[typeRule]}]`; const typeShadowColor = `[shadow=${TypeShadow[typeRule]}]`; const typeText = - typeTextColor + typeShadowColor + i18next.t(`pokemonInfo:Type.${typeRule}`)! + "[/color]" + "[/shadow]"; + typeTextColor + + typeShadowColor + + i18next.t(`pokemonInfo:type.${toCamelCase(typeRule)}`)! + + "[/color]" + + "[/shadow]"; rules.push(typeText); break; } @@ -794,15 +798,15 @@ export class RunInfoUiHandler extends UiHandler { 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 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-ES" || currentLanguage === "pt_BR" - ? i18next.t("runHistory:SPDshortened") - : i18next.t("pokemonInfo:Stat.SPDshortened"); + ? i18next.t("runHistory:spdShortened") + : i18next.t("pokemonInfo:stat.spdShortened"); const speed = speedLabel + ": " + pStats[5]; // Column 1: HP Atk Def const pokeStatText1 = addBBCodeTextObject(-5, 0, hp, TextStyle.SUMMARY, { diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 82467506720..25d5277b4c2 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -27,6 +27,7 @@ import { AbilityAttr } from "#enums/ability-attr"; import { AbilityId } from "#enums/ability-id"; import { Button } from "#enums/buttons"; import { ChallengeType } from "#enums/challenge-type"; +import { Challenges } from "#enums/challenges"; import { Device } from "#enums/devices"; import { DexAttr } from "#enums/dex-attr"; import { DropDownColumn } from "#enums/drop-down-column"; @@ -44,7 +45,7 @@ import { BattleSceneEventType } from "#events/battle-scene"; import type { Variant } from "#sprites/variant"; import { getVariantIcon, getVariantTint } from "#sprites/variant"; import { achvs } from "#system/achv"; -import type { DexAttrProps, StarterAttributes, StarterMoveset } from "#system/game-data"; +import type { DexAttrProps, StarterAttributes, StarterDataEntry, StarterMoveset } from "#system/game-data"; import { RibbonData } from "#system/ribbons/ribbon-data"; import { SettingKeyboard } from "#system/settings-keyboard"; import type { DexEntry } from "#types/dex-data"; @@ -73,7 +74,7 @@ import { import type { StarterPreferences } from "#utils/data"; import { loadStarterPreferences, saveStarterPreferences } from "#utils/data"; import { getPokemonSpeciesForm, getPokerusStarters } from "#utils/pokemon-utils"; -import { toTitleCase } from "#utils/strings"; +import { toCamelCase, toTitleCase } from "#utils/strings"; import { argbFromRgba } from "@material/material-color-utilities"; import i18next from "i18next"; import type { GameObjects } from "phaser"; @@ -300,6 +301,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { private pokemonMoveBgs: Phaser.GameObjects.NineSlice[]; private pokemonMoveLabels: Phaser.GameObjects.Text[]; private pokemonAdditionalMoveCountLabel: Phaser.GameObjects.Text; + private eggMovesLabel: Phaser.GameObjects.Text; private pokemonEggMovesContainer: Phaser.GameObjects.Container; private pokemonEggMoveContainers: Phaser.GameObjects.Container[]; private pokemonEggMoveBgs: Phaser.GameObjects.NineSlice[]; @@ -400,8 +402,16 @@ export class StarterSelectUiHandler extends MessageUiHandler { private starterSelectCallback: StarterSelectCallback | null; private starterPreferences: StarterPreferences; + private originalStarterPreferences: StarterPreferences; + + /** + * Used to check whether any moves were swapped using the reorder menu, to decide + * whether a save should be performed or not. + */ + private hasSwappedMoves = false; protected blockInput = false; + private allowTera: boolean; constructor() { super(UiMode.STARTER_SELECT); @@ -874,14 +884,14 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.pokemonEggMovesContainer = globalScene.add.container(102, 85).setScale(0.375); - const eggMovesLabel = addTextObject( + this.eggMovesLabel = addTextObject( -46, 0, i18next.t("starterSelectUiHandler:eggMoves"), TextStyle.WINDOW_ALT, ).setOrigin(0.5, 0); - this.pokemonEggMovesContainer.add(eggMovesLabel); + this.pokemonEggMovesContainer.add(this.eggMovesLabel); for (let m = 0; m < 4; m++) { const eggMoveContainer = globalScene.add.container(0, 16 + 14 * m); @@ -1126,25 +1136,31 @@ export class StarterSelectUiHandler extends MessageUiHandler { } show(args: any[]): boolean { - if (!this.starterPreferences) { - // starterPreferences haven't been loaded yet - this.starterPreferences = loadStarterPreferences(); - } this.moveInfoOverlay.clear(); // clear this when removing a menu; the cancel button doesn't seem to trigger this automatically on controllers this.pokerusSpecies = getPokerusStarters(); + this.allowTera = globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id); + if (args.length >= 1 && args[0] instanceof Function) { super.show(args); this.starterSelectCallback = args[0] as StarterSelectCallback; this.starterSelectContainer.setVisible(true); + this.starterPreferences = loadStarterPreferences(); + this.originalStarterPreferences = loadStarterPreferences(); + this.allSpecies.forEach((species, s) => { const icon = this.starterContainers[s].icon; - const dexEntry = globalScene.gameData.dexData[species.speciesId]; + const { dexEntry } = this.getSpeciesData(species.speciesId); // Initialize the StarterAttributes for this species - this.starterPreferences[species.speciesId] = this.initStarterPrefs(species); + this.starterPreferences[species.speciesId] = this.initStarterPrefs(species, this.starterPreferences); + this.originalStarterPreferences[species.speciesId] = this.initStarterPrefs( + species, + this.originalStarterPreferences, + true, + ); if (dexEntry.caughtAttr) { icon.clearTint(); @@ -1155,6 +1171,18 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.setUpgradeAnimation(icon, species); }); + const notFreshStart = !globalScene.gameMode.hasChallenge(Challenges.FRESH_START); + + for (const container of this.pokemonEggMoveContainers) { + container.setVisible(notFreshStart); + } + this.eggMovesLabel.setVisible(notFreshStart); + // This is not enough, we need individual checks in setStarterSpecies too! :) + this.pokemonPassiveDisabledIcon.setVisible(notFreshStart); + this.pokemonPassiveLabelText.setVisible(notFreshStart); + this.pokemonPassiveLockedIcon.setVisible(notFreshStart); + this.pokemonPassiveText.setVisible(notFreshStart); + this.resetFilters(); this.updateStarters(); @@ -1179,10 +1207,13 @@ export class StarterSelectUiHandler extends MessageUiHandler { * @param species The species to get Starter Preferences for * @returns StarterAttributes for the species */ - initStarterPrefs(species: PokemonSpecies): StarterAttributes { - const starterAttributes = this.starterPreferences[species.speciesId]; - const dexEntry = globalScene.gameData.dexData[species.speciesId]; - const starterData = globalScene.gameData.starterData[species.speciesId]; + initStarterPrefs( + species: PokemonSpecies, + preferences: StarterPreferences, + ignoreChallenge = false, + ): StarterAttributes { + const starterAttributes = preferences[species.speciesId]; + const { dexEntry, starterDataEntry: starterData } = this.getSpeciesData(species.speciesId, !ignoreChallenge); // no preferences or Pokemon wasn't caught, return empty attribute if (!starterAttributes || !dexEntry.caughtAttr) { @@ -1262,6 +1293,17 @@ export class StarterSelectUiHandler extends MessageUiHandler { } } + if (starterAttributes.tera !== undefined) { + // If somehow we have an illegal tera type, it is reset here + if (!(starterAttributes.tera === species.type1 || starterAttributes.tera === species?.type2)) { + starterAttributes.tera = species.type1; + } + // In fresh start challenge, the tera type is always reset to the first one + if (globalScene.gameMode.hasChallenge(Challenges.FRESH_START) && !ignoreChallenge) { + starterAttributes.tera = species.type1; + } + } + return starterAttributes; } @@ -1714,7 +1756,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { globalScene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)), this.isPartyValid(), ); - const isCaught = globalScene.gameData.dexData[species.speciesId].caughtAttr; + const isCaught = this.getSpeciesData(species.speciesId).dexEntry.caughtAttr; return ( !isDupe && isValidForChallenge && currentPartyValue + starterCost <= this.getValueLimit() && isCaught ); @@ -1781,9 +1823,14 @@ export class StarterSelectUiHandler extends MessageUiHandler { } } else { let starterContainer: StarterContainer; - const starterData = globalScene.gameData.starterData[this.lastSpecies.speciesId]; - // prepare persistent starter data to store changes + // The temporary, duplicated starter data to show info + const starterData = this.getSpeciesData(this.lastSpecies.speciesId).starterDataEntry; + // The persistent starter data to apply e.g. candy upgrades + const persistentStarterData = globalScene.gameData.starterData[this.lastSpecies.speciesId]; + // The sanitized starter preferences let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId]; + // The original starter preferences + const originalStarterAttributes = this.originalStarterPreferences[this.lastSpecies.speciesId]; // this gets the correct pokemon cursor depending on whether you're in the starter screen or the party icons if (!this.starterIconsCursorObj.visible) { @@ -1957,6 +2004,14 @@ export class StarterSelectUiHandler extends MessageUiHandler { handler: () => { this.moveInfoOverlay.clear(); this.clearText(); + // Only saved if moves were actually swapped + if (this.hasSwappedMoves) { + globalScene.gameData.saveSystem().then(success => { + if (!success) { + return globalScene.reset(true); + } + }); + } ui.setMode(UiMode.STARTER_SELECT); return true; }, @@ -1975,6 +2030,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { options.push({ label: i18next.t("starterSelectUiHandler:manageMoves"), handler: () => { + this.hasSwappedMoves = false; showSwapOptions(this.starterMoveset!); // TODO: is this bang correct? return true; }, @@ -1999,6 +2055,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { starterAttributes = this.starterPreferences[this.lastSpecies.speciesId] = {}; } starterAttributes.nature = n; + originalStarterAttributes.nature = starterAttributes.nature; this.clearText(); ui.setMode(UiMode.STARTER_SELECT); // set nature for starter @@ -2067,6 +2124,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { label: i18next.t("starterSelectUiHandler:addToFavorites"), handler: () => { starterAttributes.favorite = true; + originalStarterAttributes.favorite = true; // if the starter container not exists, it means the species is not in the filtered starters if (starterContainer) { starterContainer.favoriteIcon.setVisible(starterAttributes.favorite); @@ -2080,6 +2138,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { label: i18next.t("starterSelectUiHandler:removeFromFavorites"), handler: () => { starterAttributes.favorite = false; + originalStarterAttributes.favorite = false; // if the starter container not exists, it means the species is not in the filtered starters if (starterContainer) { starterContainer.favoriteIcon.setVisible(starterAttributes.favorite); @@ -2102,6 +2161,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { (sanitizedName: string) => { ui.playSelect(); starterAttributes.nickname = sanitizedName; + originalStarterAttributes.nickname = sanitizedName; const name = decodeURIComponent(escape(atob(starterAttributes.nickname))); if (name.length > 0) { this.pokemonNameText.setText(name); @@ -2127,15 +2187,17 @@ export class StarterSelectUiHandler extends MessageUiHandler { const options: any[] = []; // TODO: add proper type // Unlock passive option - if (!(passiveAttr & PassiveAttr.UNLOCKED)) { + if (!(passiveAttr & PassiveAttr.UNLOCKED) && !globalScene.gameMode.hasChallenge(Challenges.FRESH_START)) { const passiveCost = getPassiveCandyCount(speciesStarterCosts[this.lastSpecies.speciesId]); options.push({ label: `×${passiveCost} ${i18next.t("starterSelectUiHandler:unlockPassive")}`, handler: () => { if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= passiveCost) { - starterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED; + persistentStarterData.passiveAttr |= PassiveAttr.UNLOCKED | PassiveAttr.ENABLED; + starterData.passiveAttr = persistentStarterData.passiveAttr; if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) { - starterData.candyCount -= passiveCost; + persistentStarterData.candyCount -= passiveCost; + starterData.candyCount = persistentStarterData.candyCount; } this.pokemonCandyCountText.setText(`×${starterData.candyCount}`); globalScene.gameData.saveSystem().then(success => { @@ -2150,9 +2212,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { // update the passive background and icon/animation for available upgrade if (starterContainer) { this.updateCandyUpgradeDisplay(starterContainer); - starterContainer.starterPassiveBgs.setVisible( - !!globalScene.gameData.starterData[this.lastSpecies.speciesId].passiveAttr, - ); + starterContainer.starterPassiveBgs.setVisible(!!starterData.passiveAttr); } return true; } @@ -2165,7 +2225,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { // Reduce cost option const valueReduction = starterData.valueReduction; - if (valueReduction < valueReductionMax) { + if (valueReduction < valueReductionMax && !globalScene.gameMode.hasChallenge(Challenges.FRESH_START)) { const reductionCost = getValueReductionCandyCounts(speciesStarterCosts[this.lastSpecies.speciesId])[ valueReduction ]; @@ -2173,9 +2233,11 @@ export class StarterSelectUiHandler extends MessageUiHandler { label: `×${reductionCost} ${i18next.t("starterSelectUiHandler:reduceCost")}`, handler: () => { if (Overrides.FREE_CANDY_UPGRADE_OVERRIDE || candyCount >= reductionCost) { - starterData.valueReduction++; + persistentStarterData.valueReduction++; + starterData.valueReduction = persistentStarterData.valueReduction; if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) { - starterData.candyCount -= reductionCost; + persistentStarterData.candyCount -= reductionCost; + starterData.candyCount = persistentStarterData.candyCount; } this.pokemonCandyCountText.setText(`×${starterData.candyCount}`); globalScene.gameData.saveSystem().then(success => { @@ -2221,7 +2283,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { return false; } if (!Overrides.FREE_CANDY_UPGRADE_OVERRIDE) { - starterData.candyCount -= sameSpeciesEggCost; + persistentStarterData.candyCount -= sameSpeciesEggCost; + starterData.candyCount = persistentStarterData.candyCount; } this.pokemonCandyCountText.setText(`×${starterData.candyCount}`); @@ -2264,7 +2327,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { }); }; options.push({ - label: i18next.t("menuUiHandler:POKEDEX"), + label: i18next.t("menuUiHandler:pokedex"), handler: () => { ui.setMode(UiMode.STARTER_SELECT).then(() => { const attributes = { @@ -2273,7 +2336,18 @@ export class StarterSelectUiHandler extends MessageUiHandler { form: starterAttributes.form, female: starterAttributes.female, }; - ui.setOverlayMode(UiMode.POKEDEX_PAGE, this.lastSpecies, attributes); + ui.setOverlayMode(UiMode.POKEDEX_PAGE, this.lastSpecies, attributes, null, null, () => { + if (this.lastSpecies) { + starterContainer = this.filteredStarterContainers[this.cursor]; + const persistentStarterData = globalScene.gameData.starterData[this.lastSpecies.speciesId]; + this.updateCandyUpgradeDisplay(starterContainer); + this.updateStarterValueLabel(starterContainer); + starterContainer.starterPassiveBgs.setVisible( + !!persistentStarterData.passiveAttr && !globalScene.gameMode.hasChallenge(Challenges.FRESH_START), + ); + this.setSpecies(this.lastSpecies); + } + }); }); return true; }, @@ -2317,6 +2391,10 @@ export class StarterSelectUiHandler extends MessageUiHandler { const newVariant = starterAttributes.variant ? (starterAttributes.variant as Variant) : newProps.variant; + starterAttributes.shiny = true; + originalStarterAttributes.shiny = true; + starterAttributes.variant = newVariant; + originalStarterAttributes.variant = newVariant; this.setSpeciesDetails(this.lastSpecies, { shiny: true, variant: newVariant, @@ -2326,8 +2404,6 @@ export class StarterSelectUiHandler extends MessageUiHandler { // Cycle tint based on current sprite tint const tint = getVariantTint(newVariant); this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant)).setTint(tint).setVisible(true); - - starterAttributes.shiny = true; } else { // If shiny, we update the variant let newVariant = props.variant; @@ -2351,15 +2427,17 @@ export class StarterSelectUiHandler extends MessageUiHandler { } } while (newVariant !== props.variant); starterAttributes.variant = newVariant; // store the selected variant + originalStarterAttributes.variant = newVariant; if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.NON_SHINY && newVariant <= props.variant) { // If we have run out of variants, go back to non shiny + starterAttributes.shiny = false; + originalStarterAttributes.shiny = false; this.setSpeciesDetails(this.lastSpecies, { shiny: false, variant: 0, }); this.pokemonShinyIcon.setVisible(false); success = true; - starterAttributes.shiny = false; } else { // If going to a higher variant, or only shiny forms are caught, go to next variant this.setSpeciesDetails(this.lastSpecies, { @@ -2388,7 +2466,9 @@ export class StarterSelectUiHandler extends MessageUiHandler { } } while (newFormIndex !== props.formIndex); starterAttributes.form = newFormIndex; // store the selected form + originalStarterAttributes.form = newFormIndex; starterAttributes.tera = this.lastSpecies.forms[newFormIndex].type1; + originalStarterAttributes.tera = starterAttributes.tera; this.setSpeciesDetails(this.lastSpecies, { formIndex: newFormIndex, teraType: starterAttributes.tera, @@ -2399,6 +2479,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { case Button.CYCLE_GENDER: if (this.canCycleGender) { starterAttributes.female = !props.female; + originalStarterAttributes.female = starterAttributes.female; this.setSpeciesDetails(this.lastSpecies, { female: !props.female, }); @@ -2408,7 +2489,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { case Button.CYCLE_ABILITY: if (this.canCycleAbility) { const abilityCount = this.lastSpecies.getAbilityCount(); - const abilityAttr = globalScene.gameData.starterData[this.lastSpecies.speciesId].abilityAttr; + const abilityAttr = starterData.abilityAttr; const hasAbility1 = abilityAttr & AbilityAttr.ABILITY_1; let newAbilityIndex = this.abilityCursor; do { @@ -2430,6 +2511,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { } } while (newAbilityIndex !== this.abilityCursor); starterAttributes.ability = newAbilityIndex; // store the selected ability + originalStarterAttributes.ability = newAbilityIndex; const { visible: tooltipVisible } = globalScene.ui.getTooltip(); @@ -2451,6 +2533,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { const newNature = natures[natureIndex < natures.length - 1 ? natureIndex + 1 : 0]; // store cycled nature as default starterAttributes.nature = newNature as unknown as number; + originalStarterAttributes.nature = starterAttributes.nature; this.setSpeciesDetails(this.lastSpecies, { natureIndex: newNature, }); @@ -2461,12 +2544,14 @@ export class StarterSelectUiHandler extends MessageUiHandler { if (this.canCycleTera) { const speciesForm = getPokemonSpeciesForm(this.lastSpecies.speciesId, starterAttributes.form ?? 0); if (speciesForm.type1 === this.teraCursor && !isNullOrUndefined(speciesForm.type2)) { - starterAttributes.tera = speciesForm.type2!; + starterAttributes.tera = speciesForm.type2; + originalStarterAttributes.tera = starterAttributes.tera; this.setSpeciesDetails(this.lastSpecies, { - teraType: speciesForm.type2!, + teraType: speciesForm.type2, }); } else { starterAttributes.tera = speciesForm.type1; + originalStarterAttributes.tera = starterAttributes.tera; this.setSpeciesDetails(this.lastSpecies, { teraType: speciesForm.type1, }); @@ -2713,19 +2798,19 @@ export class StarterSelectUiHandler extends MessageUiHandler { } const updatedMoveset = starterMoveset.slice() as StarterMoveset; const formIndex = globalScene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.dexAttrCursor).formIndex; - const starterData = globalScene.gameData.starterData[speciesId]; + const starterDataEntry = globalScene.gameData.starterData[speciesId]; // species has different forms if (pokemonFormLevelMoves.hasOwnProperty(speciesId)) { // Species has forms with different movesets - if (!starterData.moveset || Array.isArray(starterData.moveset)) { - starterData.moveset = {}; + if (!starterDataEntry.moveset || Array.isArray(starterDataEntry.moveset)) { + starterDataEntry.moveset = {}; } - starterData.moveset[formIndex] = updatedMoveset; + starterDataEntry.moveset[formIndex] = updatedMoveset; } else { - starterData.moveset = updatedMoveset; + starterDataEntry.moveset = updatedMoveset; } + this.hasSwappedMoves = true; this.setSpeciesDetails(this.lastSpecies, { forSeen: false }); - this.updateSelectedStarterMoveset(speciesId); } @@ -2994,8 +3079,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { container.cost = globalScene.gameData.getSpeciesStarterValue(container.species.speciesId); // First, ensure you have the caught attributes for the species else default to bigint 0 - const caughtAttr = globalScene.gameData.dexData[container.species.speciesId]?.caughtAttr || BigInt(0); - const starterData = globalScene.gameData.starterData[container.species.speciesId]; + const { dexEntry, starterDataEntry: starterData } = this.getSpeciesData(container.species.speciesId); + const caughtAttr = dexEntry?.caughtAttr ?? BigInt(0); const isStarterProgressable = speciesEggMoves.hasOwnProperty(container.species.speciesId); // Gen filter @@ -3227,12 +3312,12 @@ export class StarterSelectUiHandler extends MessageUiHandler { onScreenFirstIndex + maxRows * maxColumns - 1, ); - const gameData = globalScene.gameData; - this.starterSelectScrollBar.setScrollCursor(this.scrollCursor); let pokerusCursorIndex = 0; this.filteredStarterContainers.forEach((container, i) => { + const { dexEntry, starterDataEntry } = this.getSpeciesData(container.species.speciesId); + const pos = calcStarterPosition(i, this.scrollCursor); container.setPosition(pos.x, pos.y); if (i < onScreenFirstIndex || i > onScreenLastIndex) { @@ -3268,10 +3353,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { container.label.setVisible(true); const speciesVariants = - speciesId && gameData.dexData[speciesId].caughtAttr & DexAttr.SHINY - ? [DexAttr.DEFAULT_VARIANT, DexAttr.VARIANT_2, DexAttr.VARIANT_3].filter( - v => !!(gameData.dexData[speciesId].caughtAttr & v), - ) + speciesId && dexEntry.caughtAttr & DexAttr.SHINY + ? [DexAttr.DEFAULT_VARIANT, DexAttr.VARIANT_2, DexAttr.VARIANT_3].filter(v => !!(dexEntry.caughtAttr & v)) : []; for (let v = 0; v < 3; v++) { const hasVariant = speciesVariants.length > v; @@ -3285,15 +3368,11 @@ export class StarterSelectUiHandler extends MessageUiHandler { } } - container.starterPassiveBgs.setVisible(!!gameData.starterData[speciesId].passiveAttr); - container.hiddenAbilityIcon.setVisible( - !!gameData.dexData[speciesId].caughtAttr && !!(gameData.starterData[speciesId].abilityAttr & 4), - ); + container.starterPassiveBgs.setVisible(!!starterDataEntry.passiveAttr); + container.hiddenAbilityIcon.setVisible(!!dexEntry.caughtAttr && !!(starterDataEntry.abilityAttr & 4)); container.classicWinIcon - .setVisible(gameData.starterData[speciesId].classicWinCount > 0) - .setTexture( - gameData.dexData[speciesId].ribbons.has(RibbonData.NUZLOCKE) ? "champion_ribbon_emerald" : "champion_ribbon", - ); + .setVisible(starterDataEntry.classicWinCount > 0) + .setTexture(dexEntry.ribbons.has(RibbonData.NUZLOCKE) ? "champion_ribbon_emerald" : "champion_ribbon"); container.favoriteIcon.setVisible(this.starterPreferences[speciesId]?.favorite ?? false); // 'Candy Icon' mode @@ -3393,11 +3472,20 @@ export class StarterSelectUiHandler extends MessageUiHandler { } setSpecies(species: PokemonSpecies | null) { - this.speciesStarterDexEntry = species ? globalScene.gameData.dexData[species.speciesId] : null; - this.dexAttrCursor = species ? this.getCurrentDexProps(species.speciesId) : 0n; - this.abilityCursor = species ? globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species) : 0; - this.natureCursor = species ? globalScene.gameData.getSpeciesDefaultNature(species) : 0; - this.teraCursor = species ? species.type1 : PokemonType.UNKNOWN; + this.speciesStarterDexEntry = null; + this.dexAttrCursor = 0n; + this.abilityCursor = 0; + this.natureCursor = 0; + this.teraCursor = PokemonType.UNKNOWN; + + if (species) { + const { dexEntry } = this.getSpeciesData(species.speciesId); + this.speciesStarterDexEntry = dexEntry; + this.dexAttrCursor = this.getCurrentDexProps(species.speciesId); + this.abilityCursor = globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species); + this.natureCursor = globalScene.gameData.getSpeciesDefaultNature(species, dexEntry); + this.teraCursor = species.type1; + } if (!species && globalScene.ui.getTooltip().visible) { globalScene.ui.hideTooltip(); @@ -3470,7 +3558,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { //Growth translate let growthReadable = toTitleCase(GrowthRate[species.growthRate]); - const growthAux = growthReadable.replace(" ", "_"); + const growthAux = toCamelCase(growthReadable); if (i18next.exists("growth:" + growthAux)) { growthReadable = i18next.t(("growth:" + growthAux) as any); } @@ -3562,11 +3650,12 @@ export class StarterSelectUiHandler extends MessageUiHandler { teraType: this.starterTeras[starterIndex], }); } else { - const defaultDexAttr = this.getCurrentDexProps(species.speciesId); const defaultAbilityIndex = starterAttributes?.ability ?? globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species); // load default nature from stater save data, if set - const defaultNature = starterAttributes?.nature || globalScene.gameData.getSpeciesDefaultNature(species); + const { dexEntry } = this.getSpeciesData(species.speciesId); + const defaultNature = + starterAttributes?.nature || globalScene.gameData.getSpeciesDefaultNature(species, dexEntry); props = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); if (starterAttributes?.variant && !Number.isNaN(starterAttributes.variant)) { if (props.shiny) { @@ -3583,6 +3672,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { variant: props.variant, abilityIndex: defaultAbilityIndex, natureIndex: defaultNature, + teraType: starterAttributes?.tera, }); } @@ -3663,14 +3753,36 @@ export class StarterSelectUiHandler extends MessageUiHandler { } } + getSpeciesData( + speciesId: SpeciesId, + applyChallenge = true, + ): { dexEntry: DexEntry; starterDataEntry: StarterDataEntry } { + const dexEntry = globalScene.gameData.dexData[speciesId]; + const starterDataEntry = globalScene.gameData.starterData[speciesId]; + + // Unpacking to make a copy by values, not references + const copiedDexEntry = { ...dexEntry }; + copiedDexEntry.ivs = [...dexEntry.ivs]; + const copiedStarterDataEntry = { ...starterDataEntry }; + if (applyChallenge) { + applyChallenges(ChallengeType.STARTER_SELECT_MODIFY, speciesId, copiedDexEntry, copiedStarterDataEntry); + } + return { dexEntry: { ...copiedDexEntry }, starterDataEntry: { ...copiedStarterDataEntry } }; + } + setSpeciesDetails(species: PokemonSpecies, options: SpeciesDetails = {}): void { let { shiny, formIndex, female, variant, abilityIndex, natureIndex, teraType } = options; const forSeen: boolean = options.forSeen ?? false; const oldProps = species ? globalScene.gameData.getSpeciesDexAttrProps(species, this.dexAttrCursor) : null; const oldAbilityIndex = this.abilityCursor > -1 ? this.abilityCursor : globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species); - const oldNatureIndex = - this.natureCursor > -1 ? this.natureCursor : globalScene.gameData.getSpeciesDefaultNature(species); + let oldNatureIndex = -1; + if (species) { + const { dexEntry } = this.getSpeciesData(species.speciesId); + oldNatureIndex = + this.natureCursor > -1 ? this.natureCursor : globalScene.gameData.getSpeciesDefaultNature(species, dexEntry); + } + const oldTeraType = this.teraCursor > -1 ? this.teraCursor : species ? species.type1 : PokemonType.UNKNOWN; this.dexAttrCursor = 0n; this.abilityCursor = -1; this.natureCursor = -1; @@ -3683,6 +3795,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { !isNullOrUndefined(shiny) || !isNullOrUndefined(variant); + const isFreshStartChallenge = globalScene.gameMode.hasChallenge(Challenges.FRESH_START); + if (this.activeTooltip === "CANDY") { if (this.lastSpecies && this.pokemonCandyContainer.visible) { const { currentFriendship, friendshipCap } = this.getFriendship(this.lastSpecies.speciesId); @@ -3717,7 +3831,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { ); // TODO: is this bang correct? this.abilityCursor = abilityIndex !== undefined ? abilityIndex : (abilityIndex = oldAbilityIndex); this.natureCursor = natureIndex !== undefined ? natureIndex : (natureIndex = oldNatureIndex); - this.teraCursor = !isNullOrUndefined(teraType) ? teraType : (teraType = species.type1); + this.teraCursor = !isNullOrUndefined(teraType) ? teraType : (teraType = oldTeraType); 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); @@ -3740,15 +3854,14 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.speciesStarterMoves = []; if (species) { - const dexEntry = globalScene.gameData.dexData[species.speciesId]; - const abilityAttr = globalScene.gameData.starterData[species.speciesId].abilityAttr; + const { dexEntry, starterDataEntry } = this.getSpeciesData(species.speciesId); + const caughtAttr = dexEntry.caughtAttr || BigInt(0); + const abilityAttr = starterDataEntry.abilityAttr; - const caughtAttr = globalScene.gameData.dexData[species.speciesId]?.caughtAttr || BigInt(0); - - if (!dexEntry.caughtAttr) { + if (!caughtAttr) { const props = globalScene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)); const defaultAbilityIndex = globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species); - const defaultNature = globalScene.gameData.getSpeciesDefaultNature(species); + const defaultNature = globalScene.gameData.getSpeciesDefaultNature(species, dexEntry); if (shiny === undefined || shiny !== props.shiny) { shiny = props.shiny; @@ -3858,8 +3971,9 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.canCycleNature = globalScene.gameData.getNaturesForAttr(dexEntry.natureAttr).length > 1; this.canCycleTera = !this.statsMode && - globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id) && - !isNullOrUndefined(getPokemonSpeciesForm(species.speciesId, formIndex ?? 0).type2); + this.allowTera && + !isNullOrUndefined(getPokemonSpeciesForm(species.speciesId, formIndex ?? 0).type2) && + !globalScene.gameMode.hasChallenge(Challenges.FRESH_START); } if (dexEntry.caughtAttr && species.malePercent !== null) { @@ -3886,7 +4000,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { .setColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD)) .setShadowColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD, true)); - const passiveAttr = globalScene.gameData.starterData[species.speciesId].passiveAttr; + const passiveAttr = starterDataEntry.passiveAttr; const passiveAbility = allAbilities[this.lastSpecies.getPassiveAbility(formIndex)]; if (this.pokemonAbilityText.visible) { @@ -3912,11 +4026,11 @@ export class StarterSelectUiHandler extends MessageUiHandler { const textAlpha = isUnlocked && isEnabled ? 1 : 0.5; this.pokemonPassiveLabelText - .setVisible(true) + .setVisible(!isFreshStartChallenge) .setColor(this.getTextColor(TextStyle.SUMMARY_ALT)) .setShadowColor(this.getTextColor(TextStyle.SUMMARY_ALT, true)); this.pokemonPassiveText - .setVisible(true) + .setVisible(!isFreshStartChallenge) .setText(passiveAbility.name) .setColor(this.getTextColor(textStyle)) .setAlpha(textAlpha) @@ -3942,9 +4056,11 @@ export class StarterSelectUiHandler extends MessageUiHandler { y: this.pokemonPassiveText.y + this.pokemonPassiveText.displayHeight / 2, }; this.pokemonPassiveDisabledIcon - .setVisible(isUnlocked && !isEnabled) + .setVisible(isUnlocked && !isEnabled && !isFreshStartChallenge) + .setPosition(iconPosition.x, iconPosition.y); + this.pokemonPassiveLockedIcon + .setVisible(!isUnlocked && !isFreshStartChallenge) .setPosition(iconPosition.x, iconPosition.y); - this.pokemonPassiveLockedIcon.setVisible(!isUnlocked).setPosition(iconPosition.x, iconPosition.y); } else if (this.activeTooltip === "PASSIVE") { // No passive and passive tooltip is active > hide it globalScene.ui.hideTooltip(); @@ -3967,13 +4083,13 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.speciesStarterMoves.push(...levelMoves.filter(lm => lm[0] > 0 && lm[0] <= 5).map(lm => lm[1])); if (speciesEggMoves.hasOwnProperty(species.speciesId)) { for (let em = 0; em < 4; em++) { - if (globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em)) { + if (starterDataEntry.eggMoves & (1 << em)) { this.speciesStarterMoves.push(speciesEggMoves[species.speciesId][em]); } } } - const speciesMoveData = globalScene.gameData.starterData[species.speciesId].moveset; + const speciesMoveData = starterDataEntry.moveset; const moveData: StarterMoveset | null = speciesMoveData ? Array.isArray(speciesMoveData) ? speciesMoveData @@ -3981,9 +4097,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { : null; const availableStarterMoves = this.speciesStarterMoves.concat( speciesEggMoves.hasOwnProperty(species.speciesId) - ? speciesEggMoves[species.speciesId].filter( - (_: any, em: number) => globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em), - ) + ? speciesEggMoves[species.speciesId].filter((_: any, em: number) => starterDataEntry.eggMoves & (1 << em)) : [], ); this.starterMoveset = (moveData || (this.speciesStarterMoves.slice(0, 4) as StarterMoveset)).filter(m => @@ -4010,9 +4124,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.setTypeIcons(speciesForm.type1, speciesForm.type2); this.teraIcon.setFrame(PokemonType[this.teraCursor].toLowerCase()); - this.teraIcon.setVisible( - !this.statsMode && globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id), - ); + this.teraIcon.setVisible(!this.statsMode && this.allowTera); } else { this.pokemonAbilityText.setText(""); this.pokemonPassiveText.setText(""); @@ -4045,10 +4157,15 @@ export class StarterSelectUiHandler extends MessageUiHandler { } const hasEggMoves = species && speciesEggMoves.hasOwnProperty(species.speciesId); + let eggMoves = 0; + if (species) { + const { starterDataEntry } = this.getSpeciesData(this.lastSpecies.speciesId); + eggMoves = starterDataEntry.eggMoves; + } for (let em = 0; em < 4; em++) { const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null; - const eggMoveUnlocked = eggMove && globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em); + const eggMoveUnlocked = eggMove && eggMoves & (1 << em); this.pokemonEggMoveBgs[em].setFrame( PokemonType[eggMove ? eggMove.type : PokemonType.UNKNOWN].toString().toLowerCase(), ); @@ -4064,6 +4181,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.tryUpdateValue(); this.updateInstructions(); + + saveStarterPreferences(this.originalStarterPreferences); } setTypeIcons(type1: PokemonType | null, type2: PokemonType | null): void { @@ -4157,9 +4276,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { textStyle = TextStyle.SUMMARY_GOLD; break; } - if (baseStarterValue - starterValue > 0) { - starter.label.setColor(this.getTextColor(textStyle)).setShadowColor(this.getTextColor(textStyle, true)); - } + starter.label.setColor(this.getTextColor(textStyle)).setShadowColor(this.getTextColor(textStyle, true)); } tryUpdateValue(add?: number, addingToParty?: boolean): boolean { @@ -4318,14 +4435,12 @@ export class StarterSelectUiHandler extends MessageUiHandler { originalStarterSelectCallback?.( new Array(this.starterSpecies.length).fill(0).map((_, i) => { const starterSpecies = thisObj.starterSpecies[i]; + const { starterDataEntry } = this.getSpeciesData(starterSpecies.speciesId); return { species: starterSpecies, dexAttr: thisObj.starterAttr[i], abilityIndex: thisObj.starterAbilityIndexes[i], - passive: !( - globalScene.gameData.starterData[starterSpecies.speciesId].passiveAttr ^ - (PassiveAttr.ENABLED | PassiveAttr.UNLOCKED) - ), + passive: !(starterDataEntry.passiveAttr ^ (PassiveAttr.ENABLED | PassiveAttr.UNLOCKED)), nature: thisObj.starterNatures[i] as Nature, teraType: thisObj.starterTeras[i] as PokemonType, moveset: thisObj.starterMovesets[i], @@ -4382,7 +4497,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { */ getCurrentDexProps(speciesId: number): bigint { let props = 0n; - const caughtAttr = globalScene.gameData.dexData[speciesId].caughtAttr; + const { dexEntry } = this.getSpeciesData(speciesId); + const caughtAttr = dexEntry.caughtAttr; /* this checks the gender of the pokemon; this works by checking a) that the starter preferences for the species exist, and if so, is it female. If so, it'll add DexAttr.FEMALE to our temp props * It then checks b) if the caughtAttr for the pokemon is female and NOT male - this means that the ONLY gender we've gotten is female, and we need to add DexAttr.FEMALE to our temp props @@ -4450,7 +4566,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.pokemonSprite.setVisible(!!this.speciesStarterDexEntry?.caughtAttr); //@ts-expect-error this.statsContainer.updateIvs(null); // TODO: resolve ts-ignore. !?!? - this.teraIcon.setVisible(globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id)); + this.teraIcon.setVisible(this.allowTera); const props = globalScene.gameData.getSpeciesDexAttrProps( this.lastSpecies, this.getCurrentDexProps(this.lastSpecies.speciesId), @@ -4458,8 +4574,9 @@ export class StarterSelectUiHandler extends MessageUiHandler { const formIndex = props.formIndex; this.canCycleTera = !this.statsMode && - globalScene.gameData.achvUnlocks.hasOwnProperty(achvs.TERASTALLIZE.id) && - !isNullOrUndefined(getPokemonSpeciesForm(this.lastSpecies.speciesId, formIndex ?? 0).type2); + this.allowTera && + !isNullOrUndefined(getPokemonSpeciesForm(this.lastSpecies.speciesId, formIndex ?? 0).type2) && + !globalScene.gameMode.hasChallenge(Challenges.FRESH_START); this.updateInstructions(); } } @@ -4501,7 +4618,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { clear(): void { super.clear(); - saveStarterPreferences(this.starterPreferences); + this.clearStarterPreferences(); this.cursor = -1; this.hideInstructions(); this.activeTooltip = undefined; @@ -4544,5 +4661,6 @@ export class StarterSelectUiHandler extends MessageUiHandler { */ clearStarterPreferences() { this.starterPreferences = {}; + this.originalStarterPreferences = {}; } } diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index b6ce0a706f8..b6447f03587 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -37,7 +37,7 @@ import { rgbHexToRgba, } from "#utils/common"; import { getEnumValues } from "#utils/enums"; -import { toTitleCase } from "#utils/strings"; +import { toCamelCase, toTitleCase } from "#utils/strings"; import { argbFromRgba } from "@material/material-color-utilities"; import i18next from "i18next"; @@ -808,8 +808,8 @@ export class SummaryUiHandler extends UiHandler { globalScene.gameData.gender === PlayerGender.FEMALE ? TextStyle.SUMMARY_PINK : TextStyle.SUMMARY_BLUE; const usernameReplacement = globalScene.gameData.gender === PlayerGender.FEMALE - ? i18next.t("trainerNames:player_f") - : i18next.t("trainerNames:player_m"); + ? i18next.t("trainerNames:playerF") + : i18next.t("trainerNames:playerM"); // TODO: should add field for original trainer name to Pokemon object, to support gift/traded Pokemon from MEs const trainerText = addBBCodeTextObject( @@ -962,7 +962,7 @@ export class SummaryUiHandler extends UiHandler { this.passiveContainer?.descriptionText?.setVisible(false); const closeFragment = getBBCodeFrag("", TextStyle.WINDOW_ALT); - const rawNature = toTitleCase(Nature[this.pokemon?.getNature()!]); // TODO: is this bang correct? + const rawNature = toCamelCase(Nature[this.pokemon?.getNature()!]); // TODO: is this bang correct? const nature = `${getBBCodeFrag(toTitleCase(getNatureName(this.pokemon?.getNature()!)), TextStyle.SUMMARY_RED)}${closeFragment}`; // TODO: is this bang correct? const memoString = i18next.t("pokemonSummary:memoString", { diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index 36e37500a64..5ae195231e5 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -122,8 +122,8 @@ export class TitleUiHandler extends OptionSelectUiHandler { genderSplash(): void { if (this.splashMessage === "splashMessages:aprilFools.helloKyleAmber") { globalScene.gameData.gender === PlayerGender.MALE - ? this.splashMessageText.setText(i18next.t(this.splashMessage, { name: i18next.t("trainerNames:player_m") })) - : this.splashMessageText.setText(i18next.t(this.splashMessage, { name: i18next.t("trainerNames:player_f") })); + ? this.splashMessageText.setText(i18next.t(this.splashMessage, { name: i18next.t("trainerNames:playerM") })) + : this.splashMessageText.setText(i18next.t(this.splashMessage, { name: i18next.t("trainerNames:playerF") })); } } diff --git a/src/utils/challenge-utils.ts b/src/utils/challenge-utils.ts index c4fac3a0323..b0c162a74ed 100644 --- a/src/utils/challenge-utils.ts +++ b/src/utils/challenge-utils.ts @@ -10,7 +10,8 @@ import type { MoveSourceType } from "#enums/move-source-type"; import type { SpeciesId } from "#enums/species-id"; import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon"; import type { ModifierTypeOption } from "#modifiers/modifier-type"; -import type { DexAttrProps } from "#system/game-data"; +import type { DexAttrProps, StarterDataEntry } from "#system/game-data"; +import type { DexEntry } from "#types/dex-data"; import { BooleanHolder, type NumberHolder } from "./common"; import { getPokemonSpecies } from "./pokemon-utils"; @@ -47,6 +48,20 @@ export function applyChallenges( species: SpeciesId, cost: NumberHolder, ): boolean; +/** + * Apply all challenges that modify selectable starter data. + * @param challengeType {@link ChallengeType} ChallengeType.STARTER_SELECT_MODIFY + * @param speciesId {@link SpeciesId} The speciesId of the pokemon + * @param dexEntry {@link DexEntry} The pokedex data associated to the pokemon. + * @param starterDataEntry {@link StarterDataEntry} The starter data associated to the pokemon. + * @returns True if any challenge was successfully applied. + */ +export function applyChallenges( + challengeType: ChallengeType.STARTER_SELECT_MODIFY, + speciesId: SpeciesId, + dexEntry: DexEntry, + starterDataEntry: StarterDataEntry, +): boolean; /** * Apply all challenges that modify a starter after selection. * @param challengeType {@link ChallengeType} ChallengeType.STARTER_MODIFY @@ -269,6 +284,9 @@ export function applyChallenges(challengeType: ChallengeType, ...args: any[]): b case ChallengeType.STARTER_COST: ret ||= c.applyStarterCost(args[0], args[1]); break; + case ChallengeType.STARTER_SELECT_MODIFY: + ret ||= c.applyStarterSelectModify(args[0], args[1], args[2]); + break; case ChallengeType.STARTER_MODIFY: ret ||= c.applyStarterModify(args[0]); break; diff --git a/src/utils/i18n.ts b/src/utils/i18n.ts new file mode 100644 index 00000000000..24f739fbb44 --- /dev/null +++ b/src/utils/i18n.ts @@ -0,0 +1,17 @@ +import { randSeedItem } from "#utils/common"; +import i18next from "i18next"; + +/** + * Select a random i18n entry from all nested keys in the given object. + * @param key - The i18n key to retrieve a random value of. + * The key's value should be an object containing numerical keys (starting from 1). + * @returns A tuple containing the key and value pair. + * @privateRemarks + * The reason such "array-like" keys are not stored as actual arrays is due to the + * translation software used by the Translation Team (Mozilla Pontoon) + * not supporting arrays in any capacity. + */ +export function getRandomLocaleEntry(key: string): [key: string, value: string] { + const keyName = `${key}.${randSeedItem(Object.keys(i18next.t(key, { returnObjects: true })))}`; + return [keyName, i18next.t(keyName)]; +} diff --git a/test/@types/vitest.d.ts b/test/@types/vitest.d.ts index 21cf76ed352..2ed0512538a 100644 --- a/test/@types/vitest.d.ts +++ b/test/@types/vitest.d.ts @@ -1,3 +1,5 @@ +import "vitest"; + import type { TerrainType } from "#app/data/terrain"; import type Overrides from "#app/overrides"; import type { ArenaTag } from "#data/arena-tag"; diff --git a/test/abilities/corrosion.test.ts b/test/abilities/corrosion.test.ts index 490a365394b..965c00290fe 100644 --- a/test/abilities/corrosion.test.ts +++ b/test/abilities/corrosion.test.ts @@ -1,6 +1,7 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; +import { StatusEffect } from "#enums/status-effect"; import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -22,25 +23,66 @@ describe("Abilities - Corrosion", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([MoveId.SPLASH]) .battleStyle("single") .criticalHits(false) .enemySpecies(SpeciesId.GRIMER) - .enemyAbility(AbilityId.CORROSION) - .enemyMoveset(MoveId.TOXIC); + .ability(AbilityId.CORROSION) + .enemyAbility(AbilityId.NO_GUARD) + .enemyMoveset(MoveId.SPLASH); }); - it("If a Poison- or Steel-type Pokémon with this Ability poisons a target with Synchronize, Synchronize does not gain the ability to poison Poison- or Steel-type Pokémon.", async () => { - game.override.ability(AbilityId.SYNCHRONIZE); - await game.classicMode.startBattle([SpeciesId.FEEBAS]); + it.each<{ name: string; species: SpeciesId }>([ + { name: "Poison", species: SpeciesId.GRIMER }, + { name: "Steel", species: SpeciesId.KLINK }, + ])("should grant the user the ability to poison $name-type opponents", async ({ species }) => { + game.override.enemySpecies(species); + await game.classicMode.startBattle([SpeciesId.SALANDIT]); - const playerPokemon = game.scene.getPlayerPokemon(); - const enemyPokemon = game.scene.getEnemyPokemon(); - expect(playerPokemon!.status).toBeUndefined(); + const enemy = game.field.getEnemyPokemon(); + expect(enemy.status?.effect).toBeUndefined(); - game.move.select(MoveId.SPLASH); - await game.phaseInterceptor.to("BerryPhase"); - expect(playerPokemon!.status).toBeDefined(); - expect(enemyPokemon!.status).toBeUndefined(); + game.move.use(MoveId.POISON_GAS); + await game.toEndOfTurn(); + + expect(enemy.status?.effect).toBe(StatusEffect.POISON); + }); + + it("should not affect Toxic Spikes", async () => { + await game.classicMode.startBattle([SpeciesId.SALANDIT]); + + game.move.use(MoveId.TOXIC_SPIKES); + await game.doKillOpponents(); + await game.toNextWave(); + + const enemyPokemon = game.field.getEnemyPokemon(); + expect(enemyPokemon.status).toBeUndefined(); + }); + + it("should not affect an opponent's Synchronize ability", async () => { + game.override.enemyAbility(AbilityId.SYNCHRONIZE); + await game.classicMode.startBattle([SpeciesId.ARBOK]); + + const playerPokemon = game.field.getPlayerPokemon(); + const enemyPokemon = game.field.getEnemyPokemon(); + expect(enemyPokemon.status?.effect).toBeUndefined(); + + game.move.use(MoveId.TOXIC); + await game.toEndOfTurn(); + + expect(enemyPokemon.status?.effect).toBe(StatusEffect.TOXIC); + expect(playerPokemon.status?.effect).toBeUndefined(); + }); + + it("should affect the user's held Toxic Orb", async () => { + game.override.startingHeldItems([{ name: "TOXIC_ORB", count: 1 }]); + await game.classicMode.startBattle([SpeciesId.SALAZZLE]); + + const salazzle = game.field.getPlayerPokemon(); + expect(salazzle.status?.effect).toBeUndefined(); + + game.move.use(MoveId.SPLASH); + await game.toNextTurn(); + + expect(salazzle.status?.effect).toBe(StatusEffect.TOXIC); }); }); diff --git a/test/abilities/disguise.test.ts b/test/abilities/disguise.test.ts index 4745d6ab609..f36501cb647 100644 --- a/test/abilities/disguise.test.ts +++ b/test/abilities/disguise.test.ts @@ -134,7 +134,7 @@ describe("Abilities - Disguise", () => { }); await game.classicMode.startBattle([SpeciesId.FURRET, SpeciesId.MIMIKYU]); - const mimikyu = game.scene.getPlayerParty()[1]!; + const mimikyu = game.scene.getPlayerParty()[1]; expect(mimikyu.formIndex).toBe(bustedForm); game.move.select(MoveId.SPLASH); diff --git a/test/abilities/embody-aspect.test.ts b/test/abilities/embody-aspect.test.ts new file mode 100644 index 00000000000..2c882c78383 --- /dev/null +++ b/test/abilities/embody-aspect.test.ts @@ -0,0 +1,70 @@ +import { AbilityId } from "#enums/ability-id"; +import { MoveId } from "#enums/move-id"; +import { SpeciesId } from "#enums/species-id"; +import { Stat } from "#enums/stat"; +import { GameManager } from "#test/test-utils/game-manager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Ability - Embody Aspect", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + const teraForm = 4; + const baseForm = 0; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .moveset([MoveId.SPLASH]) + .ability(AbilityId.EMBODY_ASPECT_TEAL) + .battleStyle("single") + .criticalHits(false) + .enemySpecies(SpeciesId.MAGIKARP) + .enemyMoveset(MoveId.SPLASH); + }); + + it("should activate on switch-in if user is Terastallized", async () => { + await game.classicMode.startBattle([SpeciesId.OGERPON, SpeciesId.ABOMASNOW]); + + const ogerpon = game.field.getPlayerPokemon(); + expect(ogerpon.formIndex).toBe(baseForm); + expect(ogerpon).toHaveStatStage(Stat.SPD, 0); + + //Terastallize Ogerpon + game.move.selectWithTera(MoveId.SPLASH); + await game.phaseInterceptor.to("QuietFormChangePhase"); + + expect(ogerpon.formIndex).toBe(teraForm); + + await game.toNextTurn(); + + expect(ogerpon).toHaveStatStage(Stat.SPD, 1); + expect(ogerpon).toHaveAbilityApplied(AbilityId.EMBODY_ASPECT_TEAL); + + // Clear out abilities applied set so we can check it again later + ogerpon.waveData.abilitiesApplied.clear(); + + //Switch ogerpon out + game.doSwitchPokemon(1); + await game.toNextTurn(); + + //Switch ogerpon back in + game.doSwitchPokemon(1); + await game.toNextTurn(); + + //Ability activated again + expect(ogerpon).toHaveStatStage(Stat.SPD, 1); + expect(ogerpon).toHaveAbilityApplied(AbilityId.EMBODY_ASPECT_TEAL); + }); +}); diff --git a/test/abilities/healer.test.ts b/test/abilities/healer.test.ts index 52f47535bf4..43280ff8271 100644 --- a/test/abilities/healer.test.ts +++ b/test/abilities/healer.test.ts @@ -49,6 +49,7 @@ describe("Abilities - Healer", () => { const user = game.field.getPlayerPokemon(); // Only want one magikarp to have the ability vi.spyOn(user, "getAbility").mockReturnValue(allAbilities[AbilityId.HEALER]); + game.move.select(MoveId.SPLASH); // faint the ally game.move.select(MoveId.LUNAR_DANCE, 1); @@ -62,9 +63,10 @@ describe("Abilities - Healer", () => { it("should heal the status of an ally if the ally has a status", async () => { await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MAGIKARP]); const [user, ally] = game.scene.getPlayerField(); + // Only want one magikarp to have the ability. vi.spyOn(user, "getAbility").mockReturnValue(allAbilities[AbilityId.HEALER]); - expect(ally.trySetStatus(StatusEffect.BURN)).toBe(true); + ally.doSetStatus(StatusEffect.BURN); game.move.select(MoveId.SPLASH); game.move.select(MoveId.SPLASH, 1); @@ -80,7 +82,7 @@ describe("Abilities - Healer", () => { const [user, ally] = game.scene.getPlayerField(); // Only want one magikarp to have the ability. vi.spyOn(user, "getAbility").mockReturnValue(allAbilities[AbilityId.HEALER]); - expect(ally.trySetStatus(StatusEffect.BURN)).toBe(true); + ally.doSetStatus(StatusEffect.BURN); game.move.select(MoveId.SPLASH); game.move.select(MoveId.SPLASH, 1); await game.phaseInterceptor.to("TurnEndPhase"); diff --git a/test/abilities/infiltrator.test.ts b/test/abilities/infiltrator.test.ts index a093fbbe6c6..24fb1b24540 100644 --- a/test/abilities/infiltrator.test.ts +++ b/test/abilities/infiltrator.test.ts @@ -79,9 +79,9 @@ describe("Abilities - Infiltrator", () => { game.scene.arena.addTag(ArenaTagType.SAFEGUARD, 1, MoveId.NONE, enemy.id, ArenaTagSide.ENEMY, true); - game.move.select(MoveId.SPORE); + game.move.use(MoveId.SPORE); + await game.toEndOfTurn(); - await game.phaseInterceptor.to("BerryPhase", false); expect(enemy.status?.effect).toBe(StatusEffect.SLEEP); expect(player.waveData.abilitiesApplied).toContain(AbilityId.INFILTRATOR); }); diff --git a/test/abilities/insomnia.test.ts b/test/abilities/insomnia.test.ts deleted file mode 100644 index 679220687b9..00000000000 --- a/test/abilities/insomnia.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { AbilityId } from "#enums/ability-id"; -import { MoveId } from "#enums/move-id"; -import { SpeciesId } from "#enums/species-id"; -import { StatusEffect } from "#enums/status-effect"; -import { GameManager } from "#test/test-utils/game-manager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -describe("Abilities - Insomnia", () => { - 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([MoveId.SPLASH]) - .ability(AbilityId.BALL_FETCH) - .battleStyle("single") - .criticalHits(false) - .enemySpecies(SpeciesId.MAGIKARP) - .enemyAbility(AbilityId.BALL_FETCH) - .enemyMoveset(MoveId.SPLASH); - }); - - it("should remove sleep when gained", async () => { - game.override - .ability(AbilityId.INSOMNIA) - .enemyAbility(AbilityId.BALL_FETCH) - .moveset(MoveId.SKILL_SWAP) - .enemyMoveset(MoveId.SPLASH); - await game.classicMode.startBattle([SpeciesId.FEEBAS]); - const enemy = game.scene.getEnemyPokemon(); - enemy?.trySetStatus(StatusEffect.SLEEP); - expect(enemy?.status?.effect).toBe(StatusEffect.SLEEP); - - game.move.select(MoveId.SKILL_SWAP); - await game.phaseInterceptor.to("BerryPhase"); - - expect(enemy?.status).toBeNull(); - }); -}); diff --git a/test/abilities/limber.test.ts b/test/abilities/limber.test.ts deleted file mode 100644 index e65a54b545d..00000000000 --- a/test/abilities/limber.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { AbilityId } from "#enums/ability-id"; -import { MoveId } from "#enums/move-id"; -import { SpeciesId } from "#enums/species-id"; -import { StatusEffect } from "#enums/status-effect"; -import { GameManager } from "#test/test-utils/game-manager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -describe("Abilities - Limber", () => { - 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([MoveId.SPLASH]) - .ability(AbilityId.BALL_FETCH) - .battleStyle("single") - .criticalHits(false) - .enemySpecies(SpeciesId.MAGIKARP) - .enemyAbility(AbilityId.BALL_FETCH) - .enemyMoveset(MoveId.SPLASH); - }); - - it("should remove paralysis when gained", async () => { - game.override - .ability(AbilityId.LIMBER) - .enemyAbility(AbilityId.BALL_FETCH) - .moveset(MoveId.SKILL_SWAP) - .enemyMoveset(MoveId.SPLASH); - await game.classicMode.startBattle([SpeciesId.FEEBAS]); - const enemy = game.scene.getEnemyPokemon(); - enemy?.trySetStatus(StatusEffect.PARALYSIS); - expect(enemy?.status?.effect).toBe(StatusEffect.PARALYSIS); - - game.move.select(MoveId.SKILL_SWAP); - await game.phaseInterceptor.to("BerryPhase"); - - expect(enemy?.status).toBeNull(); - }); -}); diff --git a/test/abilities/magma-armor.test.ts b/test/abilities/magma-armor.test.ts deleted file mode 100644 index 2e7176fdf96..00000000000 --- a/test/abilities/magma-armor.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { AbilityId } from "#enums/ability-id"; -import { MoveId } from "#enums/move-id"; -import { SpeciesId } from "#enums/species-id"; -import { StatusEffect } from "#enums/status-effect"; -import { GameManager } from "#test/test-utils/game-manager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -describe("Abilities - Magma Armor", () => { - 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([MoveId.SPLASH]) - .ability(AbilityId.BALL_FETCH) - .battleStyle("single") - .criticalHits(false) - .enemySpecies(SpeciesId.MAGIKARP) - .enemyAbility(AbilityId.BALL_FETCH) - .enemyMoveset(MoveId.SPLASH); - }); - - it("should remove freeze when gained", async () => { - game.override - .ability(AbilityId.MAGMA_ARMOR) - .enemyAbility(AbilityId.BALL_FETCH) - .moveset(MoveId.SKILL_SWAP) - .enemyMoveset(MoveId.SPLASH); - await game.classicMode.startBattle([SpeciesId.FEEBAS]); - const enemy = game.scene.getEnemyPokemon(); - enemy?.trySetStatus(StatusEffect.FREEZE); - expect(enemy?.status?.effect).toBe(StatusEffect.FREEZE); - - game.move.select(MoveId.SKILL_SWAP); - await game.phaseInterceptor.to("BerryPhase"); - - expect(enemy?.status).toBeNull(); - }); -}); diff --git a/test/abilities/moxie.test.ts b/test/abilities/moxie.test.ts index 042a8ddd058..d762187baba 100644 --- a/test/abilities/moxie.test.ts +++ b/test/abilities/moxie.test.ts @@ -3,9 +3,6 @@ import { BattlerIndex } from "#enums/battler-index"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#enums/stat"; -import { EnemyCommandPhase } from "#phases/enemy-command-phase"; -import { TurnEndPhase } from "#phases/turn-end-phase"; -import { VictoryPhase } from "#phases/victory-phase"; import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -46,7 +43,7 @@ describe("Abilities - Moxie", () => { expect(playerPokemon.getStatStage(Stat.ATK)).toBe(0); game.move.select(moveToUse); - await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(VictoryPhase); + await game.phaseInterceptor.to("VictoryPhase"); expect(playerPokemon.getStatStage(Stat.ATK)).toBe(1); }); @@ -67,7 +64,7 @@ describe("Abilities - Moxie", () => { game.move.select(moveToUse, BattlerIndex.PLAYER_2); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); expect(firstPokemon.getStatStage(Stat.ATK)).toBe(1); }, diff --git a/test/abilities/sheer-force.test.ts b/test/abilities/sheer-force.test.ts index 0e2ce85bfca..10fd454d6c2 100644 --- a/test/abilities/sheer-force.test.ts +++ b/test/abilities/sheer-force.test.ts @@ -121,8 +121,8 @@ describe("Abilities - Sheer Force", () => { await game.classicMode.startBattle([SpeciesId.PIDGEOT]); - const pidgeot = game.scene.getPlayerParty()[0]; - const onix = game.scene.getEnemyParty()[0]; + const pidgeot = game.field.getPlayerPokemon(); + const onix = game.field.getEnemyPokemon(); pidgeot.stats[Stat.DEF] = 10000; onix.stats[Stat.DEF] = 10000; diff --git a/test/abilities/shields-down.test.ts b/test/abilities/shields-down.test.ts index 98a1cfffa8e..77cec525442 100644 --- a/test/abilities/shields-down.test.ts +++ b/test/abilities/shields-down.test.ts @@ -2,14 +2,17 @@ import { Status } from "#data/status-effect"; import { AbilityId } from "#enums/ability-id"; import { BattlerTagType } from "#enums/battler-tag-type"; import { MoveId } from "#enums/move-id"; +import { MoveResult } from "#enums/move-result"; import { SpeciesId } from "#enums/species-id"; import { StatusEffect } from "#enums/status-effect"; -import { QuietFormChangePhase } from "#phases/quiet-form-change-phase"; -import { TurnEndPhase } from "#phases/turn-end-phase"; import { GameManager } from "#test/test-utils/game-manager"; -import { afterEach, beforeAll, beforeEach, describe, expect, test } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Shields Down", () => { + const redMeteorForm = 0; + const redCoreForm = 7; + const orangeCoreForm = 8; -describe("Abilities - SHIELDS DOWN", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -25,159 +28,163 @@ describe("Abilities - SHIELDS DOWN", () => { beforeEach(() => { game = new GameManager(phaserGame); - const moveToUse = MoveId.SPLASH; game.override .battleStyle("single") .ability(AbilityId.SHIELDS_DOWN) - .moveset([moveToUse]) - .enemyMoveset([MoveId.TACKLE]); + .enemySpecies(SpeciesId.PSYDUCK) + .enemyMoveset(MoveId.SPLASH); }); - test("check if fainted pokemon switched to base form on arena reset", async () => { - const meteorForm = 0, - coreForm = 7; - game.override.startingWave(4).starterForms({ - [SpeciesId.MINIOR]: coreForm, - }); + it.each([0, 1, 2, 3, 4, 5, 6])( + "should change from Meteor Form to Core Form on entry/turn end based on HP - form index %i", + async meteorIndex => { + game.override.starterForms({ + // Start in meteor form + [SpeciesId.MINIOR]: meteorIndex, + }); + await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MINIOR]); + + const minior = game.scene.getPlayerParty()[1]; + expect(minior.formIndex).toBe(meteorIndex); + minior.hp *= 0.49; + + // Switch to minior - should change to Core due to being <50% HP + game.doSwitchPokemon(1); + await game.toNextTurn(); + + expect(minior.formIndex).toBe(meteorIndex + 7); + + // Use roost to regain 50% HP; should transform back into Meteor Form at turn end + game.move.use(MoveId.ROOST); + await game.toNextTurn(); + + expect(minior.formIndex).toBe(meteorIndex); + }, + ); + + it("should revert to base form on arena reset, even when fainted", async () => { + game.override.startingWave(4).starterForms({ + [SpeciesId.MINIOR]: redCoreForm, + }); await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MINIOR]); - const minior = game.scene.getPlayerParty().find(p => p.species.speciesId === SpeciesId.MINIOR)!; - expect(minior).not.toBe(undefined); - expect(minior.formIndex).toBe(coreForm); + const minior = game.scene.getPlayerParty()[1]; + expect(minior.formIndex).toBe(redCoreForm); minior.hp = 0; minior.status = new Status(StatusEffect.FAINT); expect(minior.isFainted()).toBe(true); - game.move.select(MoveId.SPLASH); + game.move.use(MoveId.SPLASH); await game.doKillOpponents(); - await game.phaseInterceptor.to(TurnEndPhase); + await game.toEndOfTurn(); game.doSelectModifier(); - await game.phaseInterceptor.to(QuietFormChangePhase); + await game.phaseInterceptor.to("QuietFormChangePhase"); - expect(minior.formIndex).toBe(meteorForm); + expect(minior.formIndex).toBe(redMeteorForm); }); - test("should ignore non-volatile status moves", async () => { - game.override.enemyMoveset([MoveId.SPORE]); - - await game.classicMode.startBattle([SpeciesId.MINIOR]); - game.move.select(MoveId.SPLASH); - await game.phaseInterceptor.to(TurnEndPhase); - - expect(game.field.getPlayerPokemon().status).toBe(undefined); - }); - - test("should still ignore non-volatile status moves used by a pokemon with mold breaker", async () => { + // TODO: Move to mold breaker test file + it("should ignore Mold Breaker", async () => { game.override.enemyAbility(AbilityId.MOLD_BREAKER).enemyMoveset([MoveId.SPORE]); await game.classicMode.startBattle([SpeciesId.MINIOR]); - game.move.select(MoveId.SPLASH); - await game.move.selectEnemyMove(MoveId.SPORE); - await game.phaseInterceptor.to(TurnEndPhase); + game.move.use(MoveId.SPLASH); + await game.move.forceEnemyMove(MoveId.SPORE); + await game.toEndOfTurn(); - expect(game.field.getPlayerPokemon().status).toBe(undefined); + expect(game.field.getPlayerPokemon()).toHaveStatusEffect(StatusEffect.NONE); }); - test("should ignore non-volatile secondary status effects", async () => { - game.override.enemyMoveset([MoveId.NUZZLE]); - + it("should ignore non-volatile status effects & Yawn in Meteor Form", async () => { await game.classicMode.startBattle([SpeciesId.MINIOR]); - game.move.select(MoveId.SPLASH); - await game.phaseInterceptor.to(TurnEndPhase); - - expect(game.field.getPlayerPokemon().status).toBe(undefined); - }); - - test("should ignore status moves even through mold breaker", async () => { - game.override.enemyMoveset([MoveId.SPORE]).enemyAbility(AbilityId.MOLD_BREAKER); - - await game.classicMode.startBattle([SpeciesId.MINIOR]); - - game.move.select(MoveId.SPLASH); - - await game.phaseInterceptor.to(TurnEndPhase); - - expect(game.field.getPlayerPokemon().status).toBe(undefined); - }); - - // toxic spikes currently does not poison flying types when gravity is in effect - test.todo("should become poisoned by toxic spikes when grounded", async () => { - game.override - .enemyMoveset([MoveId.GRAVITY, MoveId.TOXIC_SPIKES, MoveId.SPLASH]) - .moveset([MoveId.GRAVITY, MoveId.SPLASH]); - - await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MINIOR]); - - // turn 1 - game.move.select(MoveId.GRAVITY); - await game.move.selectEnemyMove(MoveId.TOXIC_SPIKES); + game.move.use(MoveId.SPLASH); + await game.move.forceEnemyMove(MoveId.NUZZLE); + await game.toNextTurn(); + + const minior = game.field.getPlayerPokemon(); + expect(minior).toHaveStatusEffect(StatusEffect.NONE); + + game.move.use(MoveId.SPLASH); + await game.move.forceEnemyMove(MoveId.YAWN); + await game.toEndOfTurn(); + + // TODO: Yawn doesn't fail ATM when failing to be added + // expect(game.field.getEnemyPokemon()).toHaveUsedMove({ move: MoveId.YAWN, result: MoveResult.FAIL }); + expect(minior).not.toHaveBattlerTag(BattlerTagType.DROWSY); + }); + + it("should not ignore non-volatile status effects & Yawn in Core Form", async () => { + await game.classicMode.startBattle([SpeciesId.MINIOR]); + + // Drop minior to below half to prevent reverting to Core Form + const minior = game.field.getPlayerPokemon(); + minior.hp *= 0.49; + minior.formIndex = orangeCoreForm; + + game.move.use(MoveId.SPLASH); + await game.move.forceEnemyMove(MoveId.NUZZLE); + await game.toEndOfTurn(); + + expect(minior).toHaveStatusEffect(StatusEffect.PARALYSIS); + + minior.clearStatus(false, false); + expect(minior).toHaveStatusEffect(StatusEffect.NONE); + + game.move.use(MoveId.SPLASH); + await game.move.forceEnemyMove(MoveId.YAWN); + await game.toEndOfTurn(); + + expect(game.field.getEnemyPokemon()).toHaveUsedMove({ move: MoveId.YAWN, result: MoveResult.SUCCESS }); + expect(minior).toHaveBattlerTag(BattlerTagType.DROWSY); + }); + + // TODO: Gravity does not make a Pokemon be considered as "grounded" for hazards + it.todo("should be poisoned by toxic spikes when Gravity is active before changing forms", async () => { + await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MINIOR]); + + // Change minior to Core form in a state where it would revert to Meteor form on switch + const minior = game.scene.getPlayerParty()[1]; + minior.formIndex = redCoreForm; + + game.move.use(MoveId.GRAVITY); + await game.move.forceEnemyMove(MoveId.TOXIC_SPIKES); await game.toNextTurn(); - // turn 2 game.doSwitchPokemon(1); - await game.move.selectEnemyMove(MoveId.SPLASH); await game.toNextTurn(); - expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.MINIOR); - expect(game.field.getPlayerPokemon().species.formIndex).toBe(0); - expect(game.field.getPlayerPokemon().status?.effect).toBe(StatusEffect.POISON); + expect(minior.isOnField()).toBe(true); + expect(minior.formIndex).toBe(redMeteorForm); + expect(minior.isGrounded()).toBe(true); + expect(minior).toHaveStatusEffect(StatusEffect.POISON); }); - test("should ignore yawn", async () => { - game.override.enemyMoveset([MoveId.YAWN]); - - await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.MINIOR]); - - game.move.select(MoveId.SPLASH); - await game.move.selectEnemyMove(MoveId.YAWN); - - await game.phaseInterceptor.to(TurnEndPhase); - expect(game.field.getPlayerPokemon().findTag(tag => tag.tagType === BattlerTagType.DROWSY)).toBe(undefined); - }); - - test("should not ignore volatile status effects", async () => { + it("should not ignore volatile status effects", async () => { game.override.enemyMoveset([MoveId.CONFUSE_RAY]); await game.classicMode.startBattle([SpeciesId.MINIOR]); - game.move.select(MoveId.SPLASH); - await game.move.selectEnemyMove(MoveId.CONFUSE_RAY); + game.move.use(MoveId.SPLASH); + await game.move.forceEnemyMove(MoveId.CONFUSE_RAY); - await game.phaseInterceptor.to(TurnEndPhase); + await game.toEndOfTurn(); - expect(game.field.getPlayerPokemon().findTag(tag => tag.tagType === BattlerTagType.CONFUSED)).not.toBe(undefined); + expect(game.field.getPlayerPokemon()).toHaveBattlerTag(BattlerTagType.CONFUSED); }); - // the `NoTransformAbilityAbAttr` attribute is not checked anywhere, so this test cannot pass. - test.todo("ditto should not be immune to status after transforming", async () => { - game.override.enemySpecies(SpeciesId.DITTO).enemyAbility(AbilityId.IMPOSTER).moveset([MoveId.SPLASH, MoveId.SPORE]); - + // TODO: The `NoTransformAbilityAbAttr` attribute is not checked anywhere, so this test cannot pass. + // TODO: Move this to a transform test + it.todo("should not activate when transformed", async () => { + game.override.enemyAbility(AbilityId.IMPOSTER); await game.classicMode.startBattle([SpeciesId.MINIOR]); - game.move.select(MoveId.SPORE); - await game.move.selectEnemyMove(MoveId.SPLASH); + game.move.use(MoveId.SPORE); + await game.toEndOfTurn(); - await game.phaseInterceptor.to(TurnEndPhase); - expect(game.field.getEnemyPokemon().status?.effect).toBe(StatusEffect.SLEEP); - }); - - test("should not prevent minior from receiving the fainted status effect in trainer battles", async () => { - game.override - .enemyMoveset([MoveId.TACKLE]) - .moveset([MoveId.THUNDERBOLT]) - .startingLevel(100) - .startingWave(5) - .enemySpecies(SpeciesId.MINIOR); - await game.classicMode.startBattle([SpeciesId.REGIELEKI]); - const minior = game.field.getEnemyPokemon(); - - game.move.select(MoveId.THUNDERBOLT); - await game.toNextTurn(); - expect(minior.isFainted()).toBe(true); - expect(minior.status?.effect).toBe(StatusEffect.FAINT); + expect(game.field.getEnemyPokemon()).toHaveStatusEffect(StatusEffect.SLEEP); }); }); diff --git a/test/abilities/status-immunity-ab-attrs.test.ts b/test/abilities/status-immunity-ab-attrs.test.ts new file mode 100644 index 00000000000..7df621d5577 --- /dev/null +++ b/test/abilities/status-immunity-ab-attrs.test.ts @@ -0,0 +1,95 @@ +import { allMoves } from "#data/data-lists"; +import { AbilityId } from "#enums/ability-id"; +import { MoveId } from "#enums/move-id"; +import { MoveResult } from "#enums/move-result"; +import { SpeciesId } from "#enums/species-id"; +import { StatusEffect } from "#enums/status-effect"; +import { StatusEffectAttr } from "#moves/move"; +import { GameManager } from "#test/test-utils/game-manager"; +import { toTitleCase } from "#utils/strings"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +describe.each<{ name: string; ability: AbilityId; status: StatusEffect }>([ + { name: "Vital Spirit", ability: AbilityId.VITAL_SPIRIT, status: StatusEffect.SLEEP }, + { name: "Insomnia", ability: AbilityId.INSOMNIA, status: StatusEffect.SLEEP }, + { name: "Immunity", ability: AbilityId.IMMUNITY, status: StatusEffect.POISON }, + { name: "Magma Armor", ability: AbilityId.MAGMA_ARMOR, status: StatusEffect.FREEZE }, + { name: "Limber", ability: AbilityId.LIMBER, status: StatusEffect.PARALYSIS }, + { name: "Thermal Exchange", ability: AbilityId.THERMAL_EXCHANGE, status: StatusEffect.BURN }, + { name: "Water Veil", ability: AbilityId.WATER_VEIL, status: StatusEffect.BURN }, + { name: "Water Bubble", ability: AbilityId.WATER_BUBBLE, status: StatusEffect.BURN }, +])("Abilities - $name", ({ ability, status }) => { + 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 + .battleStyle("single") + .criticalHits(false) + .enemyLevel(100) + .enemySpecies(SpeciesId.MAGIKARP) + .enemyAbility(ability) + .enemyMoveset(MoveId.SPLASH); + + // Mock Lumina Crash and Spore to be our status-inflicting moves of choice + vi.spyOn(allMoves[MoveId.LUMINA_CRASH], "attrs", "get").mockReturnValue([new StatusEffectAttr(status, false)]); + vi.spyOn(allMoves[MoveId.SPORE], "attrs", "get").mockReturnValue([new StatusEffectAttr(status, false)]); + }); + + const statusStr = toTitleCase(StatusEffect[status]); + + it(`should prevent application of ${statusStr} without failing damaging moves`, async () => { + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + + const karp = game.field.getEnemyPokemon(); + expect(karp.status?.effect).toBeUndefined(); + expect(karp.canSetStatus(status)).toBe(false); + + game.move.use(MoveId.LUMINA_CRASH); + await game.toEndOfTurn(); + + expect(karp.status?.effect).toBeUndefined(); + expect(game.field.getPlayerPokemon().getLastXMoves()[0].result).toBe(MoveResult.SUCCESS); + }); + + it(`should cure ${statusStr} upon being gained`, async () => { + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + + const feebas = game.field.getPlayerPokemon(); + feebas.doSetStatus(status); + expect(feebas.status?.effect).toBe(status); + + game.move.use(MoveId.SPLASH); + await game.move.forceEnemyMove(MoveId.SKILL_SWAP); + await game.toEndOfTurn(); + + expect(feebas.status?.effect).toBeUndefined(); + }); + + // TODO: This does not propagate failures currently + it.todo( + `should cause status moves inflicting ${statusStr} to count as failed if no other effects can be applied`, + async () => { + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + + game.move.use(MoveId.SPORE); + await game.toEndOfTurn(); + + const karp = game.field.getEnemyPokemon(); + expect(karp.status?.effect).toBeUndefined(); + expect(game.field.getPlayerPokemon().getLastXMoves()[0].result).toBe(MoveResult.FAIL); + }, + ); +}); diff --git a/test/abilities/sturdy.test.ts b/test/abilities/sturdy.test.ts index 28d3098a420..4480653c12f 100644 --- a/test/abilities/sturdy.test.ts +++ b/test/abilities/sturdy.test.ts @@ -1,7 +1,6 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; -import type { EnemyPokemon } from "#field/pokemon"; import { DamageAnimPhase } from "#phases/damage-anim-phase"; import { MoveEndPhase } from "#phases/move-end-phase"; import { GameManager } from "#test/test-utils/game-manager"; @@ -38,13 +37,13 @@ describe("Abilities - Sturdy", () => { await game.classicMode.startBattle(); game.move.select(MoveId.CLOSE_COMBAT); await game.phaseInterceptor.to(MoveEndPhase); - expect(game.scene.getEnemyParty()[0].hp).toBe(1); + expect(game.field.getEnemyPokemon().hp).toBe(1); }); test("Sturdy doesn't activate when user is not at full HP", async () => { await game.classicMode.startBattle(); - const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; + const enemyPokemon = game.field.getEnemyPokemon(); enemyPokemon.hp = enemyPokemon.getMaxHp() - 1; game.move.select(MoveId.CLOSE_COMBAT); @@ -59,19 +58,7 @@ describe("Abilities - Sturdy", () => { game.move.select(MoveId.FISSURE); await game.phaseInterceptor.to(MoveEndPhase); - const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; + const enemyPokemon = game.field.getEnemyPokemon(); expect(enemyPokemon.isFullHp()).toBe(true); }); - - test("Sturdy is ignored by pokemon with `AbilityId.MOLD_BREAKER`", async () => { - game.override.ability(AbilityId.MOLD_BREAKER); - - await game.classicMode.startBattle(); - game.move.select(MoveId.CLOSE_COMBAT); - await game.phaseInterceptor.to(DamageAnimPhase); - - const enemyPokemon: EnemyPokemon = game.scene.getEnemyParty()[0]; - expect(enemyPokemon.hp).toBe(0); - expect(enemyPokemon.isFainted()).toBe(true); - }); }); diff --git a/test/abilities/thermal-exchange.test.ts b/test/abilities/thermal-exchange.test.ts deleted file mode 100644 index 193676ccc18..00000000000 --- a/test/abilities/thermal-exchange.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { AbilityId } from "#enums/ability-id"; -import { MoveId } from "#enums/move-id"; -import { SpeciesId } from "#enums/species-id"; -import { StatusEffect } from "#enums/status-effect"; -import { GameManager } from "#test/test-utils/game-manager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -describe("Abilities - Thermal Exchange", () => { - 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([MoveId.SPLASH]) - .ability(AbilityId.BALL_FETCH) - .battleStyle("single") - .criticalHits(false) - .enemySpecies(SpeciesId.MAGIKARP) - .enemyAbility(AbilityId.BALL_FETCH) - .enemyMoveset(MoveId.SPLASH); - }); - - it("should remove burn when gained", async () => { - game.override - .ability(AbilityId.THERMAL_EXCHANGE) - .enemyAbility(AbilityId.BALL_FETCH) - .moveset(MoveId.SKILL_SWAP) - .enemyMoveset(MoveId.SPLASH); - await game.classicMode.startBattle([SpeciesId.FEEBAS]); - const enemy = game.scene.getEnemyPokemon(); - enemy?.trySetStatus(StatusEffect.BURN); - expect(enemy?.status?.effect).toBe(StatusEffect.BURN); - - game.move.select(MoveId.SKILL_SWAP); - await game.phaseInterceptor.to("BerryPhase"); - - expect(enemy?.status).toBeNull(); - }); -}); diff --git a/test/abilities/vital-spirit.test.ts b/test/abilities/vital-spirit.test.ts deleted file mode 100644 index e5d80a66a8e..00000000000 --- a/test/abilities/vital-spirit.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { AbilityId } from "#enums/ability-id"; -import { MoveId } from "#enums/move-id"; -import { SpeciesId } from "#enums/species-id"; -import { StatusEffect } from "#enums/status-effect"; -import { GameManager } from "#test/test-utils/game-manager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -describe("Abilities - Vital Spirit", () => { - 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([MoveId.SPLASH]) - .ability(AbilityId.BALL_FETCH) - .battleStyle("single") - .criticalHits(false) - .enemySpecies(SpeciesId.MAGIKARP) - .enemyAbility(AbilityId.BALL_FETCH) - .enemyMoveset(MoveId.SPLASH); - }); - - it("should remove sleep when gained", async () => { - game.override - .ability(AbilityId.INSOMNIA) - .enemyAbility(AbilityId.BALL_FETCH) - .moveset(MoveId.SKILL_SWAP) - .enemyMoveset(MoveId.SPLASH); - await game.classicMode.startBattle([SpeciesId.FEEBAS]); - const enemy = game.scene.getEnemyPokemon(); - enemy?.trySetStatus(StatusEffect.SLEEP); - expect(enemy?.status?.effect).toBe(StatusEffect.SLEEP); - - game.move.select(MoveId.SKILL_SWAP); - await game.phaseInterceptor.to("BerryPhase"); - - expect(enemy?.status).toBeNull(); - }); -}); diff --git a/test/abilities/water-bubble.test.ts b/test/abilities/water-bubble.test.ts deleted file mode 100644 index 6be1ac51094..00000000000 --- a/test/abilities/water-bubble.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { AbilityId } from "#enums/ability-id"; -import { MoveId } from "#enums/move-id"; -import { SpeciesId } from "#enums/species-id"; -import { StatusEffect } from "#enums/status-effect"; -import { GameManager } from "#test/test-utils/game-manager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -describe("Abilities - Water Bubble", () => { - 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([MoveId.SPLASH]) - .ability(AbilityId.BALL_FETCH) - .battleStyle("single") - .criticalHits(false) - .enemySpecies(SpeciesId.MAGIKARP) - .enemyAbility(AbilityId.BALL_FETCH) - .enemyMoveset(MoveId.SPLASH); - }); - - it("should remove burn when gained", async () => { - game.override - .ability(AbilityId.THERMAL_EXCHANGE) - .enemyAbility(AbilityId.BALL_FETCH) - .moveset(MoveId.SKILL_SWAP) - .enemyMoveset(MoveId.SPLASH); - await game.classicMode.startBattle([SpeciesId.FEEBAS]); - const enemy = game.scene.getEnemyPokemon(); - enemy?.trySetStatus(StatusEffect.BURN); - expect(enemy?.status?.effect).toBe(StatusEffect.BURN); - - game.move.select(MoveId.SKILL_SWAP); - await game.phaseInterceptor.to("BerryPhase"); - - expect(enemy?.status).toBeNull(); - }); -}); diff --git a/test/abilities/water-veil.test.ts b/test/abilities/water-veil.test.ts deleted file mode 100644 index 0c7068ae209..00000000000 --- a/test/abilities/water-veil.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { AbilityId } from "#enums/ability-id"; -import { MoveId } from "#enums/move-id"; -import { SpeciesId } from "#enums/species-id"; -import { StatusEffect } from "#enums/status-effect"; -import { GameManager } from "#test/test-utils/game-manager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -describe("Abilities - Water Veil", () => { - 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([MoveId.SPLASH]) - .ability(AbilityId.BALL_FETCH) - .battleStyle("single") - .criticalHits(false) - .enemySpecies(SpeciesId.MAGIKARP) - .enemyAbility(AbilityId.BALL_FETCH) - .enemyMoveset(MoveId.SPLASH); - }); - - it("should remove burn when gained", async () => { - game.override - .ability(AbilityId.THERMAL_EXCHANGE) - .enemyAbility(AbilityId.BALL_FETCH) - .moveset(MoveId.SKILL_SWAP) - .enemyMoveset(MoveId.SPLASH); - await game.classicMode.startBattle([SpeciesId.FEEBAS]); - const enemy = game.scene.getEnemyPokemon(); - enemy?.trySetStatus(StatusEffect.BURN); - expect(enemy?.status?.effect).toBe(StatusEffect.BURN); - - game.move.select(MoveId.SKILL_SWAP); - await game.phaseInterceptor.to("BerryPhase"); - - expect(enemy?.status).toBeNull(); - }); -}); diff --git a/test/abilities/wimp-out.test.ts b/test/abilities/wimp-out.test.ts index 1e129f34a19..46fd5094255 100644 --- a/test/abilities/wimp-out.test.ts +++ b/test/abilities/wimp-out.test.ts @@ -336,7 +336,7 @@ describe("Abilities - Wimp Out", () => { game.move.select(MoveId.SPLASH); await game.phaseInterceptor.to("TurnEndPhase"); - expect(game.scene.getPlayerParty()[0].getHpRatio()).toEqual(0.51); + expect(game.field.getPlayerPokemon().getHpRatio()).toEqual(0.51); expect(game.phaseInterceptor.log).not.toContain("SwitchSummonPhase"); expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.WIMPOD); }); @@ -344,8 +344,7 @@ describe("Abilities - Wimp Out", () => { it("Wimp Out activating should not cancel a double battle", async () => { game.override.battleStyle("double").enemyAbility(AbilityId.WIMP_OUT).enemyMoveset([MoveId.SPLASH]).enemyLevel(1); await game.classicMode.startBattle([SpeciesId.WIMPOD, SpeciesId.TYRUNT]); - const enemyLeadPokemon = game.scene.getEnemyParty()[0]; - const enemySecPokemon = game.scene.getEnemyParty()[1]; + const [enemyLeadPokemon, enemySecPokemon] = game.scene.getEnemyParty(); game.move.select(MoveId.FALSE_SWIPE, 0, BattlerIndex.ENEMY); game.move.select(MoveId.SPLASH, 1); diff --git a/test/abilities/zero-to-hero.test.ts b/test/abilities/zero-to-hero.test.ts index d9fa3580da2..003684894df 100644 --- a/test/abilities/zero-to-hero.test.ts +++ b/test/abilities/zero-to-hero.test.ts @@ -40,8 +40,7 @@ describe("Abilities - ZERO TO HERO", () => { await game.classicMode.startBattle([SpeciesId.FEEBAS, SpeciesId.PALAFIN, SpeciesId.PALAFIN]); - const palafin1 = game.scene.getPlayerParty()[1]; - const palafin2 = game.scene.getPlayerParty()[2]; + const [, palafin1, palafin2] = game.scene.getPlayerParty(); expect(palafin1.formIndex).toBe(heroForm); expect(palafin2.formIndex).toBe(heroForm); palafin2.hp = 0; diff --git a/test/achievements/achievement.test.ts b/test/achievements/achievement.test.ts index 9060d6213cc..0608c31c469 100644 --- a/test/achievements/achievement.test.ts +++ b/test/achievements/achievement.test.ts @@ -16,21 +16,14 @@ import { NumberHolder } from "#utils/common"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -describe("check some Achievement related stuff", () => { - it("should check Achievement creation", () => { - const ach = new MoneyAchv("", "Achievement", 1000, null!, 100); - expect(ach.name).toBe("Achievement"); - }); -}); - describe("Achv", () => { let achv: Achv; beforeEach(() => { - achv = new Achv("", "Test Achievement", "This is a test achievement", "test_icon", 10); + achv = new Achv("", "This is a test achievement", "test_icon", 10); }); - it("should have the correct name", () => { + it("should have the correct description", () => { expect(achv.getDescription()).toBe("This is a test achievement"); }); @@ -53,11 +46,11 @@ describe("Achv", () => { }); it("should return the correct tier based on the score", () => { - const achv1 = new Achv("", "Test Achievement 1", "Test Description", "test_icon", 10); - const achv2 = new Achv("", "Test Achievement 2", "Test Description", "test_icon", 25); - const achv3 = new Achv("", "Test Achievement 3", "Test Description", "test_icon", 50); - const achv4 = new Achv("", "Test Achievement 4", "Test Description", "test_icon", 75); - const achv5 = new Achv("", "Test Achievement 5", "Test Description", "test_icon", 100); + const achv1 = new Achv("", "Test Description", "test_icon", 10); + const achv2 = new Achv("", "Test Description", "test_icon", 25); + const achv3 = new Achv("", "Test Description", "test_icon", 50); + const achv4 = new Achv("", "Test Description", "test_icon", 75); + const achv5 = new Achv("", "Test Description", "test_icon", 100); expect(achv1.getTier()).toBe(AchvTier.COMMON); expect(achv2.getTier()).toBe(AchvTier.GREAT); @@ -67,11 +60,11 @@ describe("Achv", () => { }); it("should validate the achievement based on the condition function", () => { - const conditionFunc = vi.fn((args: any[]) => args[0] === 10); - const achv = new Achv("", "Test Achievement", "Test Description", "test_icon", 10, conditionFunc); + const conditionFunc = vi.fn(args => args[0] === 10); + const achv2 = new Achv("", "Test Description", "test_icon", 10, conditionFunc); - expect(achv.validate([5])).toBe(false); - expect(achv.validate([10])).toBe(true); + expect(achv2.validate([5])).toBe(false); + expect(achv2.validate([10])).toBe(true); expect(conditionFunc).toHaveBeenCalledTimes(2); }); }); @@ -97,13 +90,13 @@ describe("MoneyAchv", () => { }); it("should create an instance of MoneyAchv", () => { - const moneyAchv = new MoneyAchv("", "Test Money Achievement", 10000, "money_icon", 10); + const moneyAchv = new MoneyAchv("", 10000, "money_icon", 10); expect(moneyAchv).toBeInstanceOf(MoneyAchv); expect(moneyAchv instanceof Achv).toBe(true); }); it("should validate the achievement based on the money amount", () => { - const moneyAchv = new MoneyAchv("", "Test Money Achievement", 10000, "money_icon", 10); + const moneyAchv = new MoneyAchv("", 10000, "money_icon", 10); scene.money = 5000; expect(moneyAchv.validate([])).toBe(false); @@ -134,13 +127,13 @@ describe("RibbonAchv", () => { }); it("should create an instance of RibbonAchv", () => { - const ribbonAchv = new RibbonAchv("", "Test Ribbon Achievement", 10, "ribbon_icon", 10); + const ribbonAchv = new RibbonAchv("", 10, "ribbon_icon", 10); expect(ribbonAchv).toBeInstanceOf(RibbonAchv); expect(ribbonAchv instanceof Achv).toBe(true); }); it("should validate the achievement based on the ribbon amount", () => { - const ribbonAchv = new RibbonAchv("", "Test Ribbon Achievement", 10, "ribbon_icon", 10); + const ribbonAchv = new RibbonAchv("", 10, "ribbon_icon", 10); scene.gameData.gameStats.ribbonsOwned = 5; expect(ribbonAchv.validate([])).toBe(false); @@ -152,13 +145,13 @@ describe("RibbonAchv", () => { describe("DamageAchv", () => { it("should create an instance of DamageAchv", () => { - const damageAchv = new DamageAchv("", "Test Damage Achievement", 250, "damage_icon", 10); + const damageAchv = new DamageAchv("", 250, "damage_icon", 10); expect(damageAchv).toBeInstanceOf(DamageAchv); expect(damageAchv instanceof Achv).toBe(true); }); it("should validate the achievement based on the damage amount", () => { - const damageAchv = new DamageAchv("", "Test Damage Achievement", 250, "damage_icon", 10); + const damageAchv = new DamageAchv("", 250, "damage_icon", 10); const numberHolder = new NumberHolder(200); expect(damageAchv.validate([numberHolder])).toBe(false); @@ -170,13 +163,13 @@ describe("DamageAchv", () => { describe("HealAchv", () => { it("should create an instance of HealAchv", () => { - const healAchv = new HealAchv("", "Test Heal Achievement", 250, "heal_icon", 10); + const healAchv = new HealAchv("", 250, "heal_icon", 10); expect(healAchv).toBeInstanceOf(HealAchv); expect(healAchv instanceof Achv).toBe(true); }); it("should validate the achievement based on the heal amount", () => { - const healAchv = new HealAchv("", "Test Heal Achievement", 250, "heal_icon", 10); + const healAchv = new HealAchv("", 250, "heal_icon", 10); const numberHolder = new NumberHolder(200); expect(healAchv.validate([numberHolder])).toBe(false); @@ -188,13 +181,13 @@ describe("HealAchv", () => { describe("LevelAchv", () => { it("should create an instance of LevelAchv", () => { - const levelAchv = new LevelAchv("", "Test Level Achievement", 100, "level_icon", 10); + const levelAchv = new LevelAchv("", 100, "level_icon", 10); expect(levelAchv).toBeInstanceOf(LevelAchv); expect(levelAchv instanceof Achv).toBe(true); }); it("should validate the achievement based on the level", () => { - const levelAchv = new LevelAchv("", "Test Level Achievement", 100, "level_icon", 10); + const levelAchv = new LevelAchv("", 100, "level_icon", 10); const integerHolder = new NumberHolder(50); expect(levelAchv.validate([integerHolder])).toBe(false); @@ -206,27 +199,13 @@ describe("LevelAchv", () => { describe("ModifierAchv", () => { it("should create an instance of ModifierAchv", () => { - const modifierAchv = new ModifierAchv( - "", - "Test Modifier Achievement", - "Test Description", - "modifier_icon", - 10, - () => true, - ); + const modifierAchv = new ModifierAchv("", "Test Description", "modifier_icon", 10, () => true); expect(modifierAchv).toBeInstanceOf(ModifierAchv); expect(modifierAchv instanceof Achv).toBe(true); }); it("should validate the achievement based on the modifier function", () => { - const modifierAchv = new ModifierAchv( - "", - "Test Modifier Achievement", - "Test Description", - "modifier_icon", - 10, - () => true, - ); + const modifierAchv = new ModifierAchv("", "Test Description", "modifier_icon", 10, () => true); const modifier = new TurnHeldItemTransferModifier(null!, 3, 1); expect(modifierAchv.validate([modifier])).toBe(true); diff --git a/test/battle/battle-order.test.ts b/test/battle/battle-order.test.ts index 0ee23cd6418..0b24fcbfa7d 100644 --- a/test/battle/battle-order.test.ts +++ b/test/battle/battle-order.test.ts @@ -1,9 +1,7 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; -import { EnemyCommandPhase } from "#phases/enemy-command-phase"; -import { SelectTargetPhase } from "#phases/select-target-phase"; -import { TurnStartPhase } from "#phases/turn-start-phase"; +import type { TurnStartPhase } from "#phases/turn-start-phase"; import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; @@ -41,7 +39,7 @@ describe("Battle order", () => { vi.spyOn(enemyPokemon, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 150]); // set enemyPokemon's speed to 150 game.move.select(MoveId.TACKLE); - await game.phaseInterceptor.run(EnemyCommandPhase); + await game.phaseInterceptor.to("TurnStartPhase", false); const playerPokemonIndex = playerPokemon.getBattlerIndex(); const enemyPokemonIndex = enemyPokemon.getBattlerIndex(); @@ -60,7 +58,7 @@ describe("Battle order", () => { vi.spyOn(enemyPokemon, "stats", "get").mockReturnValue([20, 20, 20, 20, 20, 50]); // set enemyPokemon's speed to 50 game.move.select(MoveId.TACKLE); - await game.phaseInterceptor.run(EnemyCommandPhase); + await game.phaseInterceptor.to("TurnStartPhase", false); const playerPokemonIndex = playerPokemon.getBattlerIndex(); const enemyPokemonIndex = enemyPokemon.getBattlerIndex(); @@ -84,7 +82,7 @@ describe("Battle order", () => { game.move.select(MoveId.TACKLE); game.move.select(MoveId.TACKLE, 1); - await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); + await game.phaseInterceptor.to("TurnStartPhase", false); const phase = game.scene.phaseManager.getCurrentPhase() as TurnStartPhase; const order = phase.getCommandOrder(); @@ -108,7 +106,7 @@ describe("Battle order", () => { game.move.select(MoveId.TACKLE); game.move.select(MoveId.TACKLE, 1); - await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); + await game.phaseInterceptor.to("TurnStartPhase", false); const phase = game.scene.phaseManager.getCurrentPhase() as TurnStartPhase; const order = phase.getCommandOrder(); @@ -132,7 +130,7 @@ describe("Battle order", () => { game.move.select(MoveId.TACKLE); game.move.select(MoveId.TACKLE, 1); - await game.phaseInterceptor.runFrom(SelectTargetPhase).to(TurnStartPhase, false); + await game.phaseInterceptor.to("TurnStartPhase", false); const phase = game.scene.phaseManager.getCurrentPhase() as TurnStartPhase; const order = phase.getCommandOrder(); diff --git a/test/battle/battle.test.ts b/test/battle/battle.test.ts index 3dd154cf4eb..36e9bdd17b0 100644 --- a/test/battle/battle.test.ts +++ b/test/battle/battle.test.ts @@ -1,28 +1,13 @@ -import { getGameMode } from "#app/game-mode"; import { allSpecies } from "#data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { BiomeId } from "#enums/biome-id"; -import { GameModes } from "#enums/game-modes"; import { MoveId } from "#enums/move-id"; -import { PlayerGender } from "#enums/player-gender"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#enums/stat"; import { UiMode } from "#enums/ui-mode"; -import { BattleEndPhase } from "#phases/battle-end-phase"; import { CommandPhase } from "#phases/command-phase"; -import { DamageAnimPhase } from "#phases/damage-anim-phase"; -import { EncounterPhase } from "#phases/encounter-phase"; -import { EnemyCommandPhase } from "#phases/enemy-command-phase"; -import { LoginPhase } from "#phases/login-phase"; import { NextEncounterPhase } from "#phases/next-encounter-phase"; -import { SelectGenderPhase } from "#phases/select-gender-phase"; -import { SelectStarterPhase } from "#phases/select-starter-phase"; -import { SummonPhase } from "#phases/summon-phase"; -import { SwitchPhase } from "#phases/switch-phase"; -import { TitlePhase } from "#phases/title-phase"; -import { TurnInitPhase } from "#phases/turn-init-phase"; import { GameManager } from "#test/test-utils/game-manager"; -import { generateStarter } from "#test/test-utils/game-manager-utils"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; @@ -45,55 +30,11 @@ describe("Phase - Battle Phase", () => { game.scene.gameData.gender = undefined!; // just for these tests! }); - it("test phase interceptor with prompt", async () => { - await game.phaseInterceptor.run(LoginPhase); - - game.onNextPrompt("SelectGenderPhase", UiMode.OPTION_SELECT, () => { - game.scene.gameData.gender = PlayerGender.MALE; - game.endPhase(); - }); - - await game.phaseInterceptor.run(SelectGenderPhase); - - await game.phaseInterceptor.run(TitlePhase); - await game.waitMode(UiMode.TITLE); - - expect(game.scene.ui?.getMode()).toBe(UiMode.TITLE); - expect(game.scene.gameData.gender).toBe(PlayerGender.MALE); - }); - - it("test phase interceptor with prompt with preparation for a future prompt", async () => { - await game.phaseInterceptor.run(LoginPhase); - - game.onNextPrompt("SelectGenderPhase", UiMode.OPTION_SELECT, () => { - game.scene.gameData.gender = PlayerGender.MALE; - game.endPhase(); - }); - - game.onNextPrompt("CheckSwitchPhase", UiMode.CONFIRM, () => { - game.setMode(UiMode.MESSAGE); - game.endPhase(); - }); - await game.phaseInterceptor.run(SelectGenderPhase); - - await game.phaseInterceptor.run(TitlePhase); - await game.waitMode(UiMode.TITLE); - - expect(game.scene.ui?.getMode()).toBe(UiMode.TITLE); - expect(game.scene.gameData.gender).toBe(PlayerGender.MALE); - }); - - it("newGame one-liner", async () => { - await game.classicMode.startBattle(); - expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); - }); - it("do attack wave 3 - single battle - regular - OHKO", async () => { game.override.enemySpecies(SpeciesId.RATTATA).startingLevel(2000).battleStyle("single").startingWave(3); await game.classicMode.startBattle([SpeciesId.MEWTWO]); game.move.use(MoveId.TACKLE); - await game.phaseInterceptor.to("SelectModifierPhase"); + await game.toNextWave(); }); it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async () => { @@ -107,7 +48,7 @@ describe("Phase - Battle Phase", () => { .battleStyle("single"); await game.classicMode.startBattle([SpeciesId.MEWTWO]); game.move.select(MoveId.TACKLE); - await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase, false); + await game.phaseInterceptor.to("TurnInitPhase", false); }); it("load 100% data file", async () => { @@ -135,68 +76,6 @@ describe("Phase - Battle Phase", () => { } }); - it("wrong phase", async () => { - await game.phaseInterceptor.run(LoginPhase); - await game.phaseInterceptor.run(LoginPhase).catch(e => { - expect(e).toBe("Wrong phase: this is SelectGenderPhase and not LoginPhase"); - }); - }); - - it("wrong phase but skip", async () => { - await game.phaseInterceptor.run(LoginPhase); - await game.phaseInterceptor.run(LoginPhase, () => game.isCurrentPhase(SelectGenderPhase)); - }); - - it("good run", async () => { - await game.phaseInterceptor.run(LoginPhase); - game.onNextPrompt( - "SelectGenderPhase", - UiMode.OPTION_SELECT, - () => { - game.scene.gameData.gender = PlayerGender.MALE; - game.endPhase(); - }, - () => game.isCurrentPhase(TitlePhase), - ); - await game.phaseInterceptor.run(SelectGenderPhase, () => game.isCurrentPhase(TitlePhase)); - await game.phaseInterceptor.run(TitlePhase); - }); - - it("good run from select gender to title", async () => { - await game.phaseInterceptor.run(LoginPhase); - game.onNextPrompt( - "SelectGenderPhase", - UiMode.OPTION_SELECT, - () => { - game.scene.gameData.gender = PlayerGender.MALE; - game.endPhase(); - }, - () => game.isCurrentPhase(TitlePhase), - ); - await game.phaseInterceptor.runFrom(SelectGenderPhase).to(TitlePhase); - }); - - it("good run to SummonPhase phase", async () => { - await game.phaseInterceptor.run(LoginPhase); - game.onNextPrompt( - "SelectGenderPhase", - UiMode.OPTION_SELECT, - () => { - game.scene.gameData.gender = PlayerGender.MALE; - game.endPhase(); - }, - () => game.isCurrentPhase(TitlePhase), - ); - game.onNextPrompt("TitlePhase", UiMode.TITLE, () => { - game.scene.gameMode = getGameMode(GameModes.CLASSIC); - const starters = generateStarter(game.scene); - const selectStarterPhase = new SelectStarterPhase(); - game.scene.phaseManager.pushPhase(new EncounterPhase(false)); - selectStarterPhase.initBattle(starters); - }); - await game.phaseInterceptor.runFrom(SelectGenderPhase).to(SummonPhase); - }); - it.each([ { name: "1v1", double: false, qty: 1 }, { name: "2v1", double: false, qty: 2 }, @@ -232,7 +111,7 @@ describe("Phase - Battle Phase", () => { await game.classicMode.startBattle([SpeciesId.DARMANITAN, SpeciesId.CHARIZARD]); game.move.select(moveToUse); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); await game.killPokemon(game.scene.currentBattle.enemyParty[0]); expect(game.scene.currentBattle.enemyParty[0].isFainted()).toBe(true); await game.phaseInterceptor.to("VictoryPhase"); @@ -296,7 +175,7 @@ describe("Phase - Battle Phase", () => { game.field.getPlayerPokemon().hp = 1; game.move.select(moveToUse); - await game.phaseInterceptor.to(BattleEndPhase); + await game.phaseInterceptor.to("BattleEndPhase"); game.doRevivePokemon(0); // pretend max revive was picked game.doSelectModifier(); @@ -308,6 +187,6 @@ describe("Phase - Battle Phase", () => { }, () => game.isCurrentPhase(NextEncounterPhase), ); - await game.phaseInterceptor.to(SwitchPhase); + await game.phaseInterceptor.to("SwitchPhase"); }); }); diff --git a/test/boss-pokemon.test.ts b/test/boss-pokemon.test.ts index b0dfbf19794..6ad405d58e6 100644 --- a/test/boss-pokemon.test.ts +++ b/test/boss-pokemon.test.ts @@ -64,11 +64,9 @@ describe("Boss Pokemon / Shields", () => { it("should reduce the number of shields if we are in a double battle", async () => { game.override.battleStyle("double").startingWave(150); // Floor 150 > 2 shields / 3 health segments - await game.classicMode.startBattle([SpeciesId.MEWTWO]); - const boss1: EnemyPokemon = game.scene.getEnemyParty()[0]!; - const boss2: EnemyPokemon = game.scene.getEnemyParty()[1]!; + const [boss1, boss2] = game.scene.getEnemyParty(); expect(boss1.isBoss()).toBe(true); expect(boss1.bossSegments).toBe(2); expect(boss2.isBoss()).toBe(true); @@ -112,7 +110,7 @@ describe("Boss Pokemon / Shields", () => { // In this test we want to break through 3 shields at once const brokenShields = 3; - const boss1: EnemyPokemon = game.scene.getEnemyParty()[0]!; + const boss1 = game.field.getEnemyPokemon(); const boss1SegmentHp = boss1.getMaxHp() / boss1.bossSegments; const requiredDamageBoss1 = boss1SegmentHp * (1 + Math.pow(2, brokenShields)); expect(boss1.isBoss()).toBe(true); @@ -124,7 +122,7 @@ describe("Boss Pokemon / Shields", () => { expect(boss1.bossSegmentIndex).toBe(1); expect(boss1.hp).toBe(boss1.getMaxHp() - toDmgValue(boss1SegmentHp * 3)); - const boss2: EnemyPokemon = game.scene.getEnemyParty()[1]!; + const boss2 = game.scene.getEnemyParty()[1]; const boss2SegmentHp = boss2.getMaxHp() / boss2.bossSegments; const requiredDamageBoss2 = boss2SegmentHp * (1 + Math.pow(2, brokenShields)); @@ -144,7 +142,7 @@ describe("Boss Pokemon / Shields", () => { await game.classicMode.startBattle([SpeciesId.MEWTWO]); - const boss1: EnemyPokemon = game.scene.getEnemyParty()[0]!; + const boss1 = game.field.getEnemyPokemon(); const boss1SegmentHp = boss1.getMaxHp() / boss1.bossSegments; const singleShieldDamage = Math.ceil(boss1SegmentHp); expect(boss1.isBoss()).toBe(true); @@ -167,7 +165,7 @@ describe("Boss Pokemon / Shields", () => { expect(getTotalStatStageBoosts(boss1)).toBe(totalStatStages); } - const boss2: EnemyPokemon = game.scene.getEnemyParty()[1]!; + const boss2 = game.scene.getEnemyParty()[1]; const boss2SegmentHp = boss2.getMaxHp() / boss2.bossSegments; const requiredDamage = boss2SegmentHp * (1 + Math.pow(2, shieldsToBreak - 1)); diff --git a/test/evolution.test.ts b/test/evolution.test.ts index afe557ff2c0..3fb763e9190 100644 --- a/test/evolution.test.ts +++ b/test/evolution.test.ts @@ -34,8 +34,7 @@ describe("Evolution", () => { it("should keep hidden ability after evolving", async () => { await game.classicMode.runToSummon([SpeciesId.EEVEE, SpeciesId.TRAPINCH]); - const eevee = game.scene.getPlayerParty()[0]; - const trapinch = game.scene.getPlayerParty()[1]; + const [eevee, trapinch] = game.scene.getPlayerParty(); eevee.abilityIndex = 2; trapinch.abilityIndex = 2; @@ -49,8 +48,7 @@ describe("Evolution", () => { it("should keep same ability slot after evolving", async () => { await game.classicMode.runToSummon([SpeciesId.BULBASAUR, SpeciesId.CHARMANDER]); - const bulbasaur = game.scene.getPlayerParty()[0]; - const charmander = game.scene.getPlayerParty()[1]; + const [bulbasaur, charmander] = game.scene.getPlayerParty(); bulbasaur.abilityIndex = 0; charmander.abilityIndex = 1; @@ -80,8 +78,7 @@ describe("Evolution", () => { nincada.gender = 1; await nincada.evolve(pokemonEvolutions[SpeciesId.NINCADA][0], nincada.getSpeciesForm()); - const ninjask = game.scene.getPlayerParty()[0]; - const shedinja = game.scene.getPlayerParty()[1]; + const [ninjask, shedinja] = game.scene.getPlayerParty(); expect(ninjask.abilityIndex).toBe(2); expect(shedinja.abilityIndex).toBe(1); expect(ninjask.gender).toBe(1); diff --git a/test/field/catching.test.ts b/test/field/catching.test.ts new file mode 100644 index 00000000000..5e732dafe93 --- /dev/null +++ b/test/field/catching.test.ts @@ -0,0 +1,299 @@ +import { pokerogueApi } from "#api/pokerogue-api"; +import { BattleType } from "#enums/battle-type"; +import { BiomeId } from "#enums/biome-id"; +import { Challenges } from "#enums/challenges"; +import { GameModes } from "#enums/game-modes"; +import { MoveId } from "#enums/move-id"; +import { PokeballType } from "#enums/pokeball"; +import { SpeciesId } from "#enums/species-id"; +import { TrainerType } from "#enums/trainer-type"; +import { GameManager } from "#test/test-utils/game-manager"; +import { mockI18next } from "#test/test-utils/test-utils"; +import i18next from "i18next"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +/** + * Helper function to run tests on cactching mons + * + * @remarks + * - Starts a run on the desired game mode, then attempts to throw a ball + * - If still in the command phase (meaning the ball did not catch) uses a move to proceed + * - If expecting success, checks that party length has increased by 1 + * - Otherwise, checks that {@link i18next} has been called on the requested error key + * + * @param game - The {@link GameManager} instance + * @param ball - The {@link PokeballType} to be used for the catch attempt + * @param expectedResult - Either "success" if the enemy should be caught, or the expected locales error key + * @param mode - One of "classic", "daily", or "challenge"; defaults to "classic". + */ +async function runPokeballTest( + game: GameManager, + ball: PokeballType, + expectedResult: string, + mode: "classic" | "daily" | "challenge" = "classic", +) { + if (mode === "classic") { + await game.classicMode.startBattle([SpeciesId.MAGIKARP]); + } else if (mode === "daily") { + // Have to do it this way because daily run is weird... + await game.runToFinalBossEncounter([SpeciesId.MAGIKARP], GameModes.DAILY); + } else if (mode === "challenge") { + await game.challengeMode.startBattle([SpeciesId.MAGIKARP]); + } + + const partyLength = game.scene.getPlayerParty().length; + + game.scene.pokeballCounts[ball] = 1; + + const tSpy = mockI18next(); + + game.doThrowPokeball(ball); + + // If still in the command phase due to ball failing, use a move to go on + if (game.isCurrentPhase("CommandPhase")) { + game.move.select(MoveId.SPLASH); + } + + await game.toEndOfTurn(); + if (expectedResult === "success") { + // Check that a mon has been caught by noticing that party length has increased + expect(game.scene.getPlayerParty()).toHaveLength(partyLength + 1); + } else { + expect(tSpy).toHaveBeenCalledWith(expectedResult); + } +} + +describe("Throwing balls in classic", () => { + 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 + .startingWave(199) + .startingBiome(BiomeId.END) + .battleStyle("single") + .moveset([MoveId.SPLASH]) + .enemyMoveset([MoveId.SPLASH]) + .startingLevel(9999); + }); + + it("throwing ball at two mons", async () => { + game.override.startingWave(21).startingBiome(BiomeId.TOWN); + game.override.battleStyle("double"); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballMulti"); + }); + + it("throwing ball in end biome", async () => { + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForce"); + }); + + it("throwing ball at two mons in end biome", async () => { + game.override.battleStyle("double"); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForce"); + }); + + it("throwing ball at two previously caught mon in end biome", async () => { + await game.importData("./test/test-utils/saves/everything.prsv"); + await runPokeballTest(game, PokeballType.MASTER_BALL, "success"); + }); + + it("throwing ball at two mons in end biome", async () => { + game.override.battleStyle("double"); + await game.importData("./test/test-utils/saves/everything.prsv"); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballMulti"); + }); + + it("throwing ball at final boss", async () => { + game.override.startingWave(200); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForceFinalBoss"); + }); + + it("throwing rogue ball at final boss with full dex", async () => { + await game.importData("./test/test-utils/saves/everything.prsv"); + game.override.startingWave(200); + await runPokeballTest(game, PokeballType.ROGUE_BALL, "battle:noPokeballForceFinalBossCatchable"); + }); + + it("throwing master ball at final boss with full dex", async () => { + await game.importData("./test/test-utils/saves/everything.prsv"); + game.override.startingWave(200); + await runPokeballTest(game, PokeballType.MASTER_BALL, "success"); + }); +}); + +describe("Throwing balls in fresh start challenge", () => { + 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.challengeMode.addChallenge(Challenges.FRESH_START, 2, 1); + game.override + .startingWave(199) + .startingBiome(BiomeId.END) + .battleStyle("single") + .moveset([MoveId.SPLASH]) + .enemyMoveset([MoveId.SPLASH]) + .startingLevel(9999); + }); + + // Tests should give the same result as a normal classic run, except for the last one + it("throwing ball in end biome", async () => { + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForce", "challenge"); + }); + + it("throwing ball at previously caught mon in end biome", async () => { + await game.importData("./test/test-utils/saves/everything.prsv"); + await runPokeballTest(game, PokeballType.MASTER_BALL, "success", "challenge"); + }); + + it("throwing ball at final boss", async () => { + game.override.startingWave(200); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForceFinalBoss", "challenge"); + }); + + it("throwing rogue ball at final boss with full dex", async () => { + await game.importData("./test/test-utils/saves/everything.prsv"); + game.override.startingWave(200); + await runPokeballTest(game, PokeballType.ROGUE_BALL, "battle:noPokeballForceFinalBossCatchable", "challenge"); + }); + + // If a challenge is active, even if the dex is complete we still need to weaken the final boss to master ball it + it("throwing ball at final boss with full dex", async () => { + await game.importData("./test/test-utils/saves/everything.prsv"); + game.override.startingWave(200); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForceFinalBossCatchable", "challenge"); + }); +}); + +describe("Throwing balls in full fresh start challenge", () => { + 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.challengeMode.addChallenge(Challenges.FRESH_START, 1, 1); + game.override + .startingWave(199) + .startingBiome(BiomeId.END) + .battleStyle("single") + .moveset([MoveId.SPLASH]) + .enemyMoveset([MoveId.SPLASH]) + .startingLevel(9999); + }); + + // Paradox mons and final boss can NEVER be caught in the full fresh start challenge + it("throwing ball at previously caught mon in end biome", async () => { + await game.importData("./test/test-utils/saves/everything.prsv"); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForce", "challenge"); + }); + + it("throwing ball at final boss with full dex", async () => { + await game.importData("./test/test-utils/saves/everything.prsv"); + game.override.startingWave(200); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForceFinalBoss", "challenge"); + }); +}); + +describe("Throwing balls in daily run", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("test-seed"); + game.override + .startingWave(50) + .startingBiome(BiomeId.END) + .battleStyle("single") + .moveset([MoveId.SPLASH]) + .enemyMoveset([MoveId.SPLASH]) + .startingLevel(9999); + }); + + it("throwing ball at daily run boss", async () => { + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForceFinalBoss", "daily"); + }); +}); + +describe("Throwing balls at trainers", () => { + 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(BattleType.TRAINER) + .randomTrainer({ trainerType: TrainerType.ACE_TRAINER }) + .moveset([MoveId.SPLASH]) + .enemyMoveset([MoveId.SPLASH]) + .startingLevel(9999); + }); + + it("throwing ball at a trainer", async () => { + game.override.startingWave(21); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballTrainer"); + }); + + it("throwing ball at a trainer in a double battle", async () => { + game.override.startingWave(21).randomTrainer({ trainerType: TrainerType.TWINS }); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballTrainer"); + }); + + it("throwing ball at a trainer in the end biome", async () => { + game.override.startingWave(195).startingBiome(BiomeId.END); + await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballTrainer"); + }); +}); diff --git a/test/abilities/immunity.test.ts b/test/field/pokemon-funcs.test.ts similarity index 55% rename from test/abilities/immunity.test.ts rename to test/field/pokemon-funcs.test.ts index dccee93ac10..eea1f80192a 100644 --- a/test/abilities/immunity.test.ts +++ b/test/field/pokemon-funcs.test.ts @@ -6,7 +6,7 @@ import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -describe("Abilities - Immunity", () => { +describe("Spec - Pokemon Functions", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -23,29 +23,29 @@ describe("Abilities - Immunity", () => { beforeEach(() => { game = new GameManager(phaserGame); game.override - .moveset([MoveId.SPLASH]) - .ability(AbilityId.BALL_FETCH) .battleStyle("single") + .startingLevel(100) .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) + .ability(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH); }); - it("should remove poison when gained", async () => { - game.override - .ability(AbilityId.IMMUNITY) - .enemyAbility(AbilityId.BALL_FETCH) - .moveset(MoveId.SKILL_SWAP) - .enemyMoveset(MoveId.SPLASH); - await game.classicMode.startBattle([SpeciesId.FEEBAS]); - const enemy = game.scene.getEnemyPokemon(); - enemy?.trySetStatus(StatusEffect.POISON); - expect(enemy?.status?.effect).toBe(StatusEffect.POISON); + describe("doSetStatus", () => { + it("should change the Pokemon's status, ignoring feasibility checks", async () => { + await game.classicMode.startBattle([SpeciesId.ACCELGOR]); - game.move.select(MoveId.SKILL_SWAP); - await game.phaseInterceptor.to("BerryPhase"); + const player = game.field.getPlayerPokemon(); - expect(enemy?.status).toBeNull(); + expect(player.status?.effect).toBeUndefined(); + player.doSetStatus(StatusEffect.BURN); + expect(player.status?.effect).toBe(StatusEffect.BURN); + + expect(player.canSetStatus(StatusEffect.SLEEP)).toBe(false); + player.doSetStatus(StatusEffect.SLEEP, 5); + expect(player.status?.effect).toBe(StatusEffect.SLEEP); + expect(player.status?.sleepTurnsRemaining).toBe(5); + }); }); }); diff --git a/test/field/pokemon.test.ts b/test/field/pokemon.test.ts index 02058ad6cb1..87a0da98f25 100644 --- a/test/field/pokemon.test.ts +++ b/test/field/pokemon.test.ts @@ -25,15 +25,6 @@ describe("Spec - Pokemon", () => { game = new GameManager(phaserGame); }); - it("should not crash when trying to set status of undefined", async () => { - await game.classicMode.runToSummon([SpeciesId.ABRA]); - - const pkm = game.field.getPlayerPokemon(); - expect(pkm).toBeDefined(); - - expect(pkm.trySetStatus(undefined)).toBe(false); - }); - describe("Add To Party", () => { let scene: BattleScene; @@ -85,17 +76,14 @@ describe("Spec - Pokemon", () => { }); describe("Get correct fusion type", () => { - let scene: BattleScene; - beforeEach(async () => { game.override.enemySpecies(SpeciesId.ZUBAT).starterSpecies(SpeciesId.ABRA).enableStarterFusion(); - scene = game.scene; }); it("Fusing two mons with a single type", async () => { game.override.starterFusionSpecies(SpeciesId.CHARMANDER); await game.classicMode.startBattle(); - const pokemon = scene.getPlayerParty()[0]; + const pokemon = game.field.getPlayerPokemon(); let types = pokemon.getTypes(); expect(types[0]).toBe(PokemonType.PSYCHIC); @@ -136,7 +124,7 @@ describe("Spec - Pokemon", () => { it("Fusing two mons with same single type", async () => { game.override.starterFusionSpecies(SpeciesId.DROWZEE); await game.classicMode.startBattle(); - const pokemon = scene.getPlayerParty()[0]; + const pokemon = game.field.getPlayerPokemon(); const types = pokemon.getTypes(); expect(types[0]).toBe(PokemonType.PSYCHIC); @@ -146,7 +134,7 @@ describe("Spec - Pokemon", () => { it("Fusing mons with one and two types", async () => { game.override.starterSpecies(SpeciesId.CHARMANDER).starterFusionSpecies(SpeciesId.HOUNDOUR); await game.classicMode.startBattle(); - const pokemon = scene.getPlayerParty()[0]; + const pokemon = game.field.getPlayerPokemon(); const types = pokemon.getTypes(); expect(types[0]).toBe(PokemonType.FIRE); @@ -156,7 +144,7 @@ describe("Spec - Pokemon", () => { it("Fusing mons with two and one types", async () => { game.override.starterSpecies(SpeciesId.NUMEL).starterFusionSpecies(SpeciesId.CHARMANDER); await game.classicMode.startBattle(); - const pokemon = scene.getPlayerParty()[0]; + const pokemon = game.field.getPlayerPokemon(); const types = pokemon.getTypes(); expect(types[0]).toBe(PokemonType.FIRE); @@ -166,7 +154,7 @@ describe("Spec - Pokemon", () => { it("Fusing two mons with two types", async () => { game.override.starterSpecies(SpeciesId.NATU).starterFusionSpecies(SpeciesId.HOUNDOUR); await game.classicMode.startBattle(); - const pokemon = scene.getPlayerParty()[0]; + const pokemon = game.field.getPlayerPokemon(); let types = pokemon.getTypes(); expect(types[0]).toBe(PokemonType.PSYCHIC); diff --git a/test/items/light-ball.test.ts b/test/items/light-ball.test.ts index a7f41255ff3..280b70f3d5a 100644 --- a/test/items/light-ball.test.ts +++ b/test/items/light-ball.test.ts @@ -33,7 +33,7 @@ describe("Items - Light Ball", () => { const consoleSpy = vi.spyOn(console, "log"); await game.classicMode.startBattle([SpeciesId.PIKACHU]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); // Checking console log to make sure Light Ball is applied when getEffectiveStat (with the appropriate stat) is called partyMember.getEffectiveStat(Stat.DEF); @@ -84,7 +84,7 @@ describe("Items - Light Ball", () => { it("LIGHT_BALL held by PIKACHU", async () => { await game.classicMode.startBattle([SpeciesId.PIKACHU]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); const atkStat = partyMember.getStat(Stat.ATK); const spAtkStat = partyMember.getStat(Stat.SPATK); @@ -113,8 +113,7 @@ describe("Items - Light Ball", () => { it("LIGHT_BALL held by fused PIKACHU (base)", async () => { await game.classicMode.startBattle([SpeciesId.PIKACHU, SpeciesId.MAROWAK]); - const partyMember = game.scene.getPlayerParty()[0]; - const ally = game.scene.getPlayerParty()[1]; + const [partyMember, ally] = game.scene.getPlayerParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -152,8 +151,7 @@ describe("Items - Light Ball", () => { it("LIGHT_BALL held by fused PIKACHU (part)", async () => { await game.classicMode.startBattle([SpeciesId.MAROWAK, SpeciesId.PIKACHU]); - const partyMember = game.scene.getPlayerParty()[0]; - const ally = game.scene.getPlayerParty()[1]; + const [partyMember, ally] = game.scene.getPlayerParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -191,7 +189,7 @@ describe("Items - Light Ball", () => { it("LIGHT_BALL not held by PIKACHU", async () => { await game.classicMode.startBattle([SpeciesId.MAROWAK]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); const atkStat = partyMember.getStat(Stat.ATK); const spAtkStat = partyMember.getStat(Stat.SPATK); diff --git a/test/items/metal-powder.test.ts b/test/items/metal-powder.test.ts index 4dac8dd39b1..1a749f0ac3d 100644 --- a/test/items/metal-powder.test.ts +++ b/test/items/metal-powder.test.ts @@ -33,7 +33,7 @@ describe("Items - Metal Powder", () => { const consoleSpy = vi.spyOn(console, "log"); await game.classicMode.startBattle([SpeciesId.DITTO]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); // Checking console log to make sure Metal Powder is applied when getEffectiveStat (with the appropriate stat) is called partyMember.getEffectiveStat(Stat.DEF); @@ -84,7 +84,7 @@ describe("Items - Metal Powder", () => { it("METAL_POWDER held by DITTO", async () => { await game.classicMode.startBattle([SpeciesId.DITTO]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); const defStat = partyMember.getStat(Stat.DEF); @@ -107,8 +107,7 @@ describe("Items - Metal Powder", () => { it("METAL_POWDER held by fused DITTO (base)", async () => { await game.classicMode.startBattle([SpeciesId.DITTO, SpeciesId.MAROWAK]); - const partyMember = game.scene.getPlayerParty()[0]; - const ally = game.scene.getPlayerParty()[1]; + const [partyMember, ally] = game.scene.getPlayerParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -140,8 +139,7 @@ describe("Items - Metal Powder", () => { it("METAL_POWDER held by fused DITTO (part)", async () => { await game.classicMode.startBattle([SpeciesId.MAROWAK, SpeciesId.DITTO]); - const partyMember = game.scene.getPlayerParty()[0]; - const ally = game.scene.getPlayerParty()[1]; + const [partyMember, ally] = game.scene.getPlayerParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -173,7 +171,7 @@ describe("Items - Metal Powder", () => { it("METAL_POWDER not held by DITTO", async () => { await game.classicMode.startBattle([SpeciesId.MAROWAK]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); const defStat = partyMember.getStat(Stat.DEF); diff --git a/test/items/quick-powder.test.ts b/test/items/quick-powder.test.ts index 2200e8cf96e..0295361ed13 100644 --- a/test/items/quick-powder.test.ts +++ b/test/items/quick-powder.test.ts @@ -33,7 +33,7 @@ describe("Items - Quick Powder", () => { const consoleSpy = vi.spyOn(console, "log"); await game.classicMode.startBattle([SpeciesId.DITTO]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); // Checking console log to make sure Quick Powder is applied when getEffectiveStat (with the appropriate stat) is called partyMember.getEffectiveStat(Stat.DEF); @@ -84,7 +84,7 @@ describe("Items - Quick Powder", () => { it("QUICK_POWDER held by DITTO", async () => { await game.classicMode.startBattle([SpeciesId.DITTO]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); const spdStat = partyMember.getStat(Stat.SPD); @@ -107,8 +107,7 @@ describe("Items - Quick Powder", () => { it("QUICK_POWDER held by fused DITTO (base)", async () => { await game.classicMode.startBattle([SpeciesId.DITTO, SpeciesId.MAROWAK]); - const partyMember = game.scene.getPlayerParty()[0]; - const ally = game.scene.getPlayerParty()[1]; + const [partyMember, ally] = game.scene.getPlayerParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -140,8 +139,7 @@ describe("Items - Quick Powder", () => { it("QUICK_POWDER held by fused DITTO (part)", async () => { await game.classicMode.startBattle([SpeciesId.MAROWAK, SpeciesId.DITTO]); - const partyMember = game.scene.getPlayerParty()[0]; - const ally = game.scene.getPlayerParty()[1]; + const [partyMember, ally] = game.scene.getPlayerParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -173,7 +171,7 @@ describe("Items - Quick Powder", () => { it("QUICK_POWDER not held by DITTO", async () => { await game.classicMode.startBattle([SpeciesId.MAROWAK]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); const spdStat = partyMember.getStat(Stat.SPD); diff --git a/test/items/temp-stat-stage-booster.test.ts b/test/items/temp-stat-stage-booster.test.ts index f95fe553faf..05ea5a03eae 100644 --- a/test/items/temp-stat-stage-booster.test.ts +++ b/test/items/temp-stat-stage-booster.test.ts @@ -6,7 +6,6 @@ import { SpeciesId } from "#enums/species-id"; import { BATTLE_STATS, Stat } from "#enums/stat"; import { UiMode } from "#enums/ui-mode"; import { TempStatStageBoosterModifier } from "#modifiers/modifier"; -import { TurnEndPhase } from "#phases/turn-end-phase"; import { GameManager } from "#test/test-utils/game-manager"; import type { ModifierSelectUiHandler } from "#ui/modifier-select-ui-handler"; import Phaser from "phaser"; @@ -47,7 +46,7 @@ describe("Items - Temporary Stat Stage Boosters", () => { game.move.select(MoveId.TACKLE); - await game.phaseInterceptor.runFrom("EnemyCommandPhase").to(TurnEndPhase); + await game.toEndOfTurn(); expect(partyMember.getStatStageMultiplier).toHaveReturnedWith(1.3); }); @@ -64,11 +63,11 @@ describe("Items - Temporary Stat Stage Boosters", () => { // Raise ACC by +2 stat stages game.move.select(MoveId.HONE_CLAWS); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); game.move.select(MoveId.TACKLE); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); // ACC at +3 stat stages yields a x2 multiplier expect(partyMember.getAccuracyMultiplier).toHaveReturnedWith(2); @@ -84,11 +83,11 @@ describe("Items - Temporary Stat Stage Boosters", () => { // Raise ATK by +1 stat stage game.move.select(MoveId.HONE_CLAWS); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); game.move.select(MoveId.TACKLE); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); // ATK at +1 stat stage yields a x1.5 multiplier, add 0.3 from X_ATTACK expect(partyMember.getStatStageMultiplier).toHaveReturnedWith(1.8); @@ -112,7 +111,7 @@ describe("Items - Temporary Stat Stage Boosters", () => { game.move.select(MoveId.TACKLE); - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("TurnEndPhase"); expect(partyMember.getAccuracyMultiplier).toHaveReturnedWith(3); expect(partyMember.getStatStageMultiplier).toHaveReturnedWith(4); diff --git a/test/items/thick-club.test.ts b/test/items/thick-club.test.ts index c497cef6338..d14b4f955e7 100644 --- a/test/items/thick-club.test.ts +++ b/test/items/thick-club.test.ts @@ -33,7 +33,7 @@ describe("Items - Thick Club", () => { const consoleSpy = vi.spyOn(console, "log"); await game.classicMode.startBattle([SpeciesId.CUBONE]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); // Checking console log to make sure Thick Club is applied when getEffectiveStat (with the appropriate stat) is called partyMember.getEffectiveStat(Stat.DEF); @@ -84,7 +84,7 @@ describe("Items - Thick Club", () => { it("THICK_CLUB held by CUBONE", async () => { await game.classicMode.startBattle([SpeciesId.CUBONE]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); const atkStat = partyMember.getStat(Stat.ATK); @@ -107,7 +107,7 @@ describe("Items - Thick Club", () => { it("THICK_CLUB held by MAROWAK", async () => { await game.classicMode.startBattle([SpeciesId.MAROWAK]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); const atkStat = partyMember.getStat(Stat.ATK); @@ -130,7 +130,7 @@ describe("Items - Thick Club", () => { it("THICK_CLUB held by ALOLA_MAROWAK", async () => { await game.classicMode.startBattle([SpeciesId.ALOLA_MAROWAK]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); const atkStat = partyMember.getStat(Stat.ATK); @@ -157,8 +157,7 @@ describe("Items - Thick Club", () => { await game.classicMode.startBattle([species[randSpecies], SpeciesId.PIKACHU]); - const partyMember = game.scene.getPlayerParty()[0]; - const ally = game.scene.getPlayerParty()[1]; + const [partyMember, ally] = game.scene.getPlayerParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -194,8 +193,7 @@ describe("Items - Thick Club", () => { await game.classicMode.startBattle([SpeciesId.PIKACHU, species[randSpecies]]); - const partyMember = game.scene.getPlayerParty()[0]; - const ally = game.scene.getPlayerParty()[1]; + const [partyMember, ally] = game.scene.getPlayerParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) partyMember.fusionSpecies = ally.species; @@ -227,7 +225,7 @@ describe("Items - Thick Club", () => { it("THICK_CLUB not held by CUBONE", async () => { await game.classicMode.startBattle([SpeciesId.PIKACHU]); - const partyMember = game.scene.getPlayerParty()[0]; + const partyMember = game.field.getPlayerPokemon(); const atkStat = partyMember.getStat(Stat.ATK); diff --git a/test/moves/aurora-veil.test.ts b/test/moves/aurora-veil.test.ts index 3c7c86c7fdf..6edc214d580 100644 --- a/test/moves/aurora-veil.test.ts +++ b/test/moves/aurora-veil.test.ts @@ -19,7 +19,7 @@ describe("Moves - Aurora Veil", () => { let phaserGame: Phaser.Game; let game: GameManager; const singleBattleMultiplier = 0.5; - const doubleBattleMultiplier = 2732 / 4096; + const doubleBattleMultiplier = 2 / 3; beforeAll(() => { phaserGame = new Phaser.Game({ diff --git a/test/moves/beat-up.test.ts b/test/moves/beat-up.test.ts index cfb3d35bed5..ff08b55cefa 100644 --- a/test/moves/beat-up.test.ts +++ b/test/moves/beat-up.test.ts @@ -73,7 +73,7 @@ describe("Moves - Beat Up", () => { const playerPokemon = game.field.getPlayerPokemon(); - game.scene.getPlayerParty()[1].trySetStatus(StatusEffect.BURN); + game.scene.getPlayerParty()[1].doSetStatus(StatusEffect.BURN); game.move.select(MoveId.BEAT_UP); diff --git a/test/moves/ceaseless-edge.test.ts b/test/moves/ceaseless-edge.test.ts index 64f4cf15511..b06ea84308c 100644 --- a/test/moves/ceaseless-edge.test.ts +++ b/test/moves/ceaseless-edge.test.ts @@ -1,4 +1,4 @@ -import { ArenaTrapTag } from "#data/arena-tag"; +import { EntryHazardTag } from "#data/arena-tag"; import { allMoves } from "#data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagSide } from "#enums/arena-tag-side"; @@ -50,12 +50,12 @@ describe("Moves - Ceaseless Edge", () => { await game.phaseInterceptor.to(MoveEffectPhase, false); // Spikes should not have any layers before move effect is applied - const tagBefore = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag; - expect(tagBefore instanceof ArenaTrapTag).toBeFalsy(); + const tagBefore = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; + expect(tagBefore instanceof EntryHazardTag).toBeFalsy(); await game.phaseInterceptor.to(TurnEndPhase); - const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag; - expect(tagAfter instanceof ArenaTrapTag).toBeTruthy(); + const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; + expect(tagAfter instanceof EntryHazardTag).toBeTruthy(); expect(tagAfter.layers).toBe(1); expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); }); @@ -72,12 +72,12 @@ describe("Moves - Ceaseless Edge", () => { await game.phaseInterceptor.to(MoveEffectPhase, false); // Spikes should not have any layers before move effect is applied - const tagBefore = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag; - expect(tagBefore instanceof ArenaTrapTag).toBeFalsy(); + const tagBefore = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; + expect(tagBefore instanceof EntryHazardTag).toBeFalsy(); await game.phaseInterceptor.to(TurnEndPhase); - const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag; - expect(tagAfter instanceof ArenaTrapTag).toBeTruthy(); + const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; + expect(tagAfter instanceof EntryHazardTag).toBeTruthy(); expect(tagAfter.layers).toBe(2); expect(enemyPokemon.hp).toBeLessThan(enemyStartingHp); }); @@ -90,12 +90,12 @@ describe("Moves - Ceaseless Edge", () => { game.move.select(MoveId.CEASELESS_EDGE); await game.phaseInterceptor.to(MoveEffectPhase, false); // Spikes should not have any layers before move effect is applied - const tagBefore = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag; - expect(tagBefore instanceof ArenaTrapTag).toBeFalsy(); + const tagBefore = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; + expect(tagBefore instanceof EntryHazardTag).toBeFalsy(); await game.toNextTurn(); - const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag; - expect(tagAfter instanceof ArenaTrapTag).toBeTruthy(); + const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; + expect(tagAfter instanceof EntryHazardTag).toBeTruthy(); expect(tagAfter.layers).toBe(2); const hpBeforeSpikes = game.scene.currentBattle.enemyParty[1].hp; diff --git a/test/moves/destiny-bond.test.ts b/test/moves/destiny-bond.test.ts index 9c397717335..118a45e7682 100644 --- a/test/moves/destiny-bond.test.ts +++ b/test/moves/destiny-bond.test.ts @@ -1,4 +1,4 @@ -import type { ArenaTrapTag } from "#data/arena-tag"; +import type { EntryHazardTag } from "#data/arena-tag"; import { allMoves } from "#data/data-lists"; import { AbilityId } from "#enums/ability-id"; import { ArenaTagSide } from "#enums/arena-tag-side"; @@ -195,7 +195,7 @@ describe("Moves - Destiny Bond", () => { expect(playerPokemon.isFainted()).toBe(true); // Ceaseless Edge spikes effect should still activate - const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as ArenaTrapTag; + const tagAfter = game.scene.arena.getTagOnSide(ArenaTagType.SPIKES, ArenaTagSide.ENEMY) as EntryHazardTag; expect(tagAfter.tagType).toBe(ArenaTagType.SPIKES); expect(tagAfter.layers).toBe(1); }); @@ -220,7 +220,10 @@ describe("Moves - Destiny Bond", () => { 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; + const tagAfter = game.scene.arena.getTagOnSide( + ArenaTagType.GRASS_WATER_PLEDGE, + ArenaTagSide.ENEMY, + ) as EntryHazardTag; expect(tagAfter.tagType).toBe(ArenaTagType.GRASS_WATER_PLEDGE); }); diff --git a/test/moves/dragon-rage.test.ts b/test/moves/dragon-rage.test.ts index c90e2b78abd..dffdbf9badc 100644 --- a/test/moves/dragon-rage.test.ts +++ b/test/moves/dragon-rage.test.ts @@ -46,7 +46,7 @@ describe("Moves - Dragon Rage", () => { await game.classicMode.startBattle(); - partyPokemon = game.scene.getPlayerParty()[0]; + partyPokemon = game.field.getPlayerPokemon(); enemyPokemon = game.field.getEnemyPokemon(); }); diff --git a/test/moves/dragon-tail.test.ts b/test/moves/dragon-tail.test.ts index 1cea6f908a0..e3a5bf459e8 100644 --- a/test/moves/dragon-tail.test.ts +++ b/test/moves/dragon-tail.test.ts @@ -76,10 +76,9 @@ describe("Moves - Dragon Tail", () => { game.override.battleStyle("double").enemyMoveset(MoveId.SPLASH).enemyAbility(AbilityId.ROUGH_SKIN); await game.classicMode.startBattle([SpeciesId.DRATINI, SpeciesId.DRATINI, SpeciesId.WAILORD, SpeciesId.WAILORD]); - const leadPokemon = game.scene.getPlayerParty()[0]!; + const leadPokemon = game.field.getPlayerPokemon(); - const enemyLeadPokemon = game.scene.getEnemyParty()[0]!; - const enemySecPokemon = game.scene.getEnemyParty()[1]!; + const [enemyLeadPokemon, enemySecPokemon] = game.scene.getEnemyParty(); game.move.select(MoveId.DRAGON_TAIL, 0, BattlerIndex.ENEMY); game.move.select(MoveId.SPLASH, 1); @@ -105,11 +104,9 @@ describe("Moves - Dragon Tail", () => { game.override.battleStyle("double").enemyMoveset(MoveId.SPLASH).enemyAbility(AbilityId.ROUGH_SKIN); await game.classicMode.startBattle([SpeciesId.DRATINI, SpeciesId.DRATINI, SpeciesId.WAILORD, SpeciesId.WAILORD]); - const leadPokemon = game.scene.getPlayerParty()[0]!; - const secPokemon = game.scene.getPlayerParty()[1]!; + const [leadPokemon, secPokemon] = game.scene.getPlayerParty(); - const enemyLeadPokemon = game.scene.getEnemyParty()[0]!; - const enemySecPokemon = game.scene.getEnemyParty()[1]!; + const [enemyLeadPokemon, enemySecPokemon] = game.scene.getEnemyParty(); game.move.select(MoveId.DRAGON_TAIL, 0, BattlerIndex.ENEMY); // target the same pokemon, second move should be redirected after first flees diff --git a/test/moves/entry-hazards.test.ts b/test/moves/entry-hazards.test.ts new file mode 100644 index 00000000000..c4dead1bb67 --- /dev/null +++ b/test/moves/entry-hazards.test.ts @@ -0,0 +1,233 @@ +import { getPokemonNameWithAffix } from "#app/messages"; +import { allMoves } from "#data/data-lists"; +import type { TypeDamageMultiplier } from "#data/type"; +import { AbilityId } from "#enums/ability-id"; +import { ArenaTagSide } from "#enums/arena-tag-side"; +import { ArenaTagType } from "#enums/arena-tag-type"; +import { BattleType } from "#enums/battle-type"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveId } from "#enums/move-id"; +import { MoveResult } from "#enums/move-result"; +import { PokemonType } from "#enums/pokemon-type"; +import { SpeciesId } from "#enums/species-id"; +import { Stat } from "#enums/stat"; +import { StatusEffect } from "#enums/status-effect"; +import { GameManager } from "#test/test-utils/game-manager"; +import type { EntryHazardTagType } from "#types/arena-tags"; +import i18next from "i18next"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Moves - Entry Hazards", () => { + 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 + .battleStyle("single") + .enemySpecies(SpeciesId.BLISSEY) + .startingLevel(100) + .enemyLevel(100) + .enemyAbility(AbilityId.BALL_FETCH) + .ability(AbilityId.BALL_FETCH) + .enemyMoveset(MoveId.SPLASH) + .battleType(BattleType.TRAINER); + }); + + describe.each<{ name: string; move: MoveId; tagType: EntryHazardTagType }>([ + { name: "Spikes", move: MoveId.SPIKES, tagType: ArenaTagType.SPIKES }, + { + name: "Toxic Spikes", + move: MoveId.TOXIC_SPIKES, + tagType: ArenaTagType.TOXIC_SPIKES, + }, + { + name: "Stealth Rock", + move: MoveId.STEALTH_ROCK, + tagType: ArenaTagType.STEALTH_ROCK, + }, + { + name: "Sticky Web", + move: MoveId.STICKY_WEB, + tagType: ArenaTagType.STICKY_WEB, + }, + ])("General checks - $name", ({ move, tagType }) => { + it("should add a persistent tag to the opposing side of the field", async () => { + await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]); + + expect(game).not.toHaveArenaTag(tagType); + + game.move.use(move); + await game.toNextTurn(); + + // Tag should've been added to the opposing side of the field + expect(game).not.toHaveArenaTag(tagType, ArenaTagSide.PLAYER); + expect(game).toHaveArenaTag(tagType, ArenaTagSide.ENEMY); + }); + + // TODO: re-enable after re-fixing hazards moves + it.todo("should work when all targets fainted", async () => { + game.override.battleStyle("double"); + await game.classicMode.startBattle([SpeciesId.RAYQUAZA, SpeciesId.SHUCKLE]); + + const [enemy1, enemy2] = game.scene.getEnemyField(); + + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER); + game.move.use(move, BattlerIndex.PLAYER_2); + await game.doKillOpponents(); + await game.toEndOfTurn(); + + expect(enemy1.isFainted()).toBe(true); + expect(enemy2.isFainted()).toBe(true); + expect(game).toHaveArenaTag(tagType, ArenaTagSide.ENEMY); + }); + + const maxLayers = tagType === ArenaTagType.SPIKES ? 3 : tagType === ArenaTagType.TOXIC_SPIKES ? 2 : 1; + const msgText = + maxLayers === 1 + ? "should fail if added while already present" + : `can be added up to ${maxLayers} times in a row before failing`; + + it(msgText, async () => { + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + + const feebas = game.field.getPlayerPokemon(); + + // set up hazards until at max layers + for (let i = 0; i < maxLayers; i++) { + game.move.use(move); + await game.toNextTurn(); + + expect(feebas).toHaveUsedMove({ move, result: MoveResult.SUCCESS }); + expect(game).toHaveArenaTag({ tagType, side: ArenaTagSide.ENEMY, layers: i + 1 }); + } + + game.move.use(move); + await game.toNextTurn(); + + expect(feebas).toHaveUsedMove({ move, result: MoveResult.FAIL }); + expect(game).toHaveArenaTag({ tagType, side: ArenaTagSide.ENEMY, layers: maxLayers }); + }); + }); + + describe("Spikes", () => { + it.each<{ layers: number; damage: number }>([ + { layers: 1, damage: 12.5 }, + { layers: 2, damage: 100 / 6 }, + { layers: 3, damage: 25 }, + ])("should play message and deal $damage% of the target's max HP at $layers", async ({ layers, damage }) => { + for (let i = 0; i < layers; i++) { + game.scene.arena.addTag(ArenaTagType.SPIKES, 0, undefined, 0, ArenaTagSide.ENEMY); + } + + await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]); + + const enemy = game.field.getEnemyPokemon(); + expect(enemy).toHaveTakenDamage((enemy.getMaxHp() * damage) / 100); + expect(game.textInterceptor.logs).toContain( + i18next.t("arenaTag:spikesActivateTrap", { + pokemonNameWithAffix: getPokemonNameWithAffix(enemy), + }), + ); + }); + }); + + describe("Toxic Spikes", () => { + it.each<{ name: string; layers: number; status: StatusEffect }>([ + { name: "Poison", layers: 1, status: StatusEffect.POISON }, + { name: "Toxic", layers: 2, status: StatusEffect.TOXIC }, + ])("should apply $name at $layers without displaying neutralization msg", async ({ layers, status }) => { + for (let i = 0; i < layers; i++) { + game.scene.arena.addTag(ArenaTagType.TOXIC_SPIKES, 0, undefined, 0, ArenaTagSide.ENEMY); + } + await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]); + + const enemy = game.field.getEnemyPokemon(); + expect(enemy).toHaveStatusEffect(status); + expect(game.textInterceptor.logs).not.toContain( + i18next.t("arenaTag:toxicSpikesActivateTrapPoison", { + pokemonNameWithAffix: getPokemonNameWithAffix(enemy), + moveName: allMoves[MoveId.TOXIC_SPIKES].name, + }), + ); + }); + }); + + it("should be removed without triggering upon a grounded Poison-type switching in", async () => { + await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.EKANS]); + + game.scene.arena.addTag(ArenaTagType.TOXIC_SPIKES, 0, undefined, 0, ArenaTagSide.ENEMY); + + game.doSwitchPokemon(1); + await game.toNextTurn(); + + const ekans = game.field.getPlayerPokemon(); + expect(game).not.toHaveArenaTag(ArenaTagType.TOXIC_SPIKES, ArenaTagSide.PLAYER); + expect(game.textInterceptor.logs).not.toContain( + i18next.t("arenaTag:toxicSpikesActivateTrapPoison", { + pokemonNameWithAffix: getPokemonNameWithAffix(ekans), + moveName: allMoves[MoveId.TOXIC_SPIKES].name, + }), + ); + expect(ekans).not.toHaveStatusEffect(StatusEffect.POISON); + }); + + describe("Stealth Rock", () => { + it.each<{ multi: TypeDamageMultiplier; species: SpeciesId }>([ + { multi: 0.25, species: SpeciesId.LUCARIO }, + { multi: 0.5, species: SpeciesId.DURALUDON }, + { multi: 1, species: SpeciesId.LICKILICKY }, + { multi: 2, species: SpeciesId.DARMANITAN }, + { multi: 4, species: SpeciesId.DELIBIRD }, + ])("should deal damage based on the target's weakness to Rock - $multi", async ({ multi, species }) => { + game.override.enemySpecies(species); + game.scene.arena.addTag(ArenaTagType.STEALTH_ROCK, 0, undefined, 0, ArenaTagSide.ENEMY); + await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.EKANS]); + + const enemy = game.field.getEnemyPokemon(); + expect(enemy.getAttackTypeEffectiveness(PokemonType.ROCK, undefined, true)).toBe(multi); + expect(enemy).toHaveTakenDamage(enemy.getMaxHp() * 0.125 * multi); + expect(game.textInterceptor.logs).toContain( + i18next.t("arenaTag:stealthRockActivateTrap", { + pokemonName: getPokemonNameWithAffix(enemy), + }), + ); + }); + + it("should ignore strong winds for type effectiveness", async () => { + game.override.enemyAbility(AbilityId.DELTA_STREAM).enemySpecies(SpeciesId.RAYQUAZA); + game.scene.arena.addTag(ArenaTagType.STEALTH_ROCK, 0, undefined, 0, ArenaTagSide.ENEMY); + await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.EKANS]); + + const rayquaza = game.field.getEnemyPokemon(); + // took 25% damage despite strong winds halving effectiveness + expect(rayquaza).toHaveTakenDamage(rayquaza.getMaxHp() * 0.25); + }); + }); + + describe("Sticky Web", () => { + it("should lower the target's speed by 1 stage on entry", async () => { + game.scene.arena.addTag(ArenaTagType.STICKY_WEB, 0, undefined, 0, ArenaTagSide.ENEMY); + await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.EKANS]); + + const enemy = game.field.getEnemyPokemon(); + expect(enemy).toHaveStatStage(Stat.SPD, -1); + expect(game.textInterceptor.logs).toContain( + i18next.t("arenaTag:stickyWebActivateTrap", { + pokemonName: enemy.getNameToRender(), + }), + ); + }); + }); +}); diff --git a/test/moves/fissure.test.ts b/test/moves/fissure.test.ts index b22b81906a6..b5255d75d73 100644 --- a/test/moves/fissure.test.ts +++ b/test/moves/fissure.test.ts @@ -42,7 +42,7 @@ describe("Moves - Fissure", () => { await game.classicMode.startBattle(); - partyPokemon = game.scene.getPlayerParty()[0]; + partyPokemon = game.field.getPlayerPokemon(); enemyPokemon = game.field.getEnemyPokemon(); }); diff --git a/test/moves/fusion-flare-bolt.test.ts b/test/moves/fusion-flare-bolt.test.ts index 42cc1248325..f5d556bde48 100644 --- a/test/moves/fusion-flare-bolt.test.ts +++ b/test/moves/fusion-flare-bolt.test.ts @@ -4,10 +4,7 @@ import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#enums/stat"; import type { Move } from "#moves/move"; -import { DamageAnimPhase } from "#phases/damage-anim-phase"; -import { MoveEffectPhase } from "#phases/move-effect-phase"; -import { MoveEndPhase } from "#phases/move-end-phase"; -import { MovePhase } from "#phases/move-phase"; +import type { MoveEffectPhase } from "#phases/move-effect-phase"; import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; @@ -55,14 +52,14 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { // Force user party to act before enemy party await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionFlare.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(100); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionBolt.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(200); }); @@ -75,14 +72,14 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { // Force user party to act before enemy party await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionBolt.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionFlare.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200); }); @@ -95,19 +92,19 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { // 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.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionFlare.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(100); - await game.phaseInterceptor.to(MoveEndPhase); + await game.phaseInterceptor.to("MoveEndPhase"); // Skip enemy move; because the enemy is at full HP, Rest should fail - await game.phaseInterceptor.runFrom(MovePhase).to(MoveEndPhase); + await game.phaseInterceptor.to("MoveEndPhase"); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionBolt.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(200); }); @@ -121,18 +118,18 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { // Force first enemy to act in between party await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionFlare.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(100); - await game.phaseInterceptor.to(MoveEndPhase); + await game.phaseInterceptor.to("MoveEndPhase"); // Skip enemy move - await game.phaseInterceptor.runFrom(MovePhase).to(MoveEndPhase); + await game.phaseInterceptor.to("MoveEndPhase"); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionBolt.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100); }); @@ -145,14 +142,14 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { // Force user party to act before enemy party await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionBolt.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionFlare.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200); }); @@ -189,24 +186,24 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { // Force first enemy to act in between party await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionBolt.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionFlare.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionBolt.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(200); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionFlare.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200); }); @@ -243,24 +240,24 @@ describe("Moves - Fusion Flare and Fusion Bolt", () => { // Force first enemy to act in between party await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY_2, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY]); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionBolt.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(100); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionFlare.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionBolt.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionBolt.calculateBattlePower).toHaveLastReturnedWith(200); - await game.phaseInterceptor.to(MoveEffectPhase, false); + await game.phaseInterceptor.to("MoveEffectPhase", false); expect((game.scene.phaseManager.getCurrentPhase() as MoveEffectPhase).move.id).toBe(fusionFlare.id); - await game.phaseInterceptor.to(DamageAnimPhase, false); + await game.phaseInterceptor.to("DamageAnimPhase", false); expect(fusionFlare.calculateBattlePower).toHaveLastReturnedWith(200); }); }); diff --git a/test/moves/fusion-flare.test.ts b/test/moves/fusion-flare.test.ts index dd8ae11683d..e5c45c8fadb 100644 --- a/test/moves/fusion-flare.test.ts +++ b/test/moves/fusion-flare.test.ts @@ -44,7 +44,7 @@ describe("Moves - Fusion Flare", () => { await game.phaseInterceptor.to(TurnStartPhase, false); // Inflict freeze quietly and check if it was properly inflicted - partyMember.trySetStatus(StatusEffect.FREEZE, false); + partyMember.doSetStatus(StatusEffect.FREEZE); expect(partyMember.status!.effect).toBe(StatusEffect.FREEZE); await game.toNextTurn(); diff --git a/test/moves/growth.test.ts b/test/moves/growth.test.ts index 4c892f0dee2..3d3b407f28b 100644 --- a/test/moves/growth.test.ts +++ b/test/moves/growth.test.ts @@ -2,8 +2,6 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#enums/stat"; -import { EnemyCommandPhase } from "#phases/enemy-command-phase"; -import { TurnInitPhase } from "#phases/turn-init-phase"; import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -40,7 +38,7 @@ describe("Moves - Growth", () => { expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(0); game.move.select(MoveId.GROWTH); - await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase); + await game.toEndOfTurn(); expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1); }); diff --git a/test/moves/light-screen.test.ts b/test/moves/light-screen.test.ts index c8282037f20..b6eb2725346 100644 --- a/test/moves/light-screen.test.ts +++ b/test/moves/light-screen.test.ts @@ -19,7 +19,7 @@ describe("Moves - Light Screen", () => { let phaserGame: Phaser.Game; let game: GameManager; const singleBattleMultiplier = 0.5; - const doubleBattleMultiplier = 2732 / 4096; + const doubleBattleMultiplier = 2 / 3; beforeAll(() => { phaserGame = new Phaser.Game({ diff --git a/test/moves/parting-shot.test.ts b/test/moves/parting-shot.test.ts index 660edc4565a..e9400aef29b 100644 --- a/test/moves/parting-shot.test.ts +++ b/test/moves/parting-shot.test.ts @@ -2,10 +2,6 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#enums/stat"; -import { BerryPhase } from "#phases/berry-phase"; -import { FaintPhase } from "#phases/faint-phase"; -import { MessagePhase } from "#phases/message-phase"; -import { TurnInitPhase } from "#phases/turn-init-phase"; import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, test } from "vitest"; @@ -43,7 +39,7 @@ describe("Moves - Parting Shot", () => { game.move.select(MoveId.PARTING_SHOT); - await game.phaseInterceptor.to(BerryPhase, false); + await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(SpeciesId.MURKROW); @@ -58,7 +54,7 @@ describe("Moves - Parting Shot", () => { game.move.select(MoveId.PARTING_SHOT); - await game.phaseInterceptor.to(BerryPhase, false); + await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(SpeciesId.MURKROW); @@ -79,24 +75,24 @@ describe("Moves - Parting Shot", () => { // use Memento 3 times to debuff enemy game.move.select(MoveId.MEMENTO); - await game.phaseInterceptor.to(FaintPhase); - expect(game.scene.getPlayerParty()[0].isFainted()).toBe(true); + await game.phaseInterceptor.to("FaintPhase"); + expect(game.field.getPlayerPokemon().isFainted()).toBe(true); game.doSelectPartyPokemon(1); - await game.phaseInterceptor.to(TurnInitPhase, false); + await game.phaseInterceptor.to("TurnInitPhase", false); game.move.select(MoveId.MEMENTO); - await game.phaseInterceptor.to(FaintPhase); - expect(game.scene.getPlayerParty()[0].isFainted()).toBe(true); + await game.phaseInterceptor.to("FaintPhase"); + expect(game.field.getPlayerPokemon().isFainted()).toBe(true); game.doSelectPartyPokemon(2); - await game.phaseInterceptor.to(TurnInitPhase, false); + await game.phaseInterceptor.to("TurnInitPhase", false); game.move.select(MoveId.MEMENTO); - await game.phaseInterceptor.to(FaintPhase); - expect(game.scene.getPlayerParty()[0].isFainted()).toBe(true); + await game.phaseInterceptor.to("FaintPhase"); + expect(game.field.getPlayerPokemon().isFainted()).toBe(true); game.doSelectPartyPokemon(3); // set up done - await game.phaseInterceptor.to(TurnInitPhase, false); + await game.phaseInterceptor.to("TurnInitPhase", false); const enemyPokemon = game.field.getEnemyPokemon(); expect(enemyPokemon).toBeDefined(); @@ -106,7 +102,7 @@ describe("Moves - Parting Shot", () => { // now parting shot should fail game.move.select(MoveId.PARTING_SHOT); - await game.phaseInterceptor.to(BerryPhase, false); + await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-6); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(-6); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(SpeciesId.MURKROW); @@ -125,7 +121,7 @@ describe("Moves - Parting Shot", () => { game.move.select(MoveId.PARTING_SHOT); - await game.phaseInterceptor.to(BerryPhase, false); + await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(SpeciesId.MURKROW); @@ -144,7 +140,7 @@ describe("Moves - Parting Shot", () => { game.move.select(MoveId.PARTING_SHOT); - await game.phaseInterceptor.to(BerryPhase, false); + await game.phaseInterceptor.to("BerryPhase", false); expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(0); expect(game.scene.getPlayerField()[0].species.speciesId).toBe(SpeciesId.MURKROW); @@ -153,43 +149,24 @@ describe("Moves - Parting Shot", () => { it.todo( // 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.classicMode.startBattle([SpeciesId.MURKROW]); - - const enemyPokemon = game.field.getEnemyPokemon(); - expect(enemyPokemon).toBeDefined(); - - game.move.select(MoveId.PARTING_SHOT); - - await game.phaseInterceptor.to(BerryPhase, false); - expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(-1); - expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(-1); - expect(game.scene.getPlayerField()[0].species.speciesId).toBe(SpeciesId.MURKROW); - }, - ); - - it.todo( - // TODO: fix this bug to pass the test! - "Parting shot regularly not fail if no party available to switch - party fainted", + "should lower stats without failing if no alive party members available to switch", async () => { await game.classicMode.startBattle([SpeciesId.MURKROW, SpeciesId.MEOWTH]); + + const meowth = game.scene.getPlayerParty()[1]; + meowth.hp = 0; + game.move.select(MoveId.SPLASH); + await game.toNextTurn(); - // intentionally kill party pokemon, switch to second slot (now 1 party mon is fainted) - await game.killPokemon(game.scene.getPlayerParty()[0]); - expect(game.scene.getPlayerParty()[0].isFainted()).toBe(true); - await game.phaseInterceptor.run(MessagePhase); - game.doSelectPartyPokemon(1); - - await game.phaseInterceptor.to(TurnInitPhase, false); game.move.select(MoveId.PARTING_SHOT); + game.doSelectPartyPokemon(1); + await game.toEndOfTurn(); - await game.phaseInterceptor.to(BerryPhase, false); const enemyPokemon = game.field.getEnemyPokemon(); expect(enemyPokemon.getStatStage(Stat.ATK)).toBe(0); expect(enemyPokemon.getStatStage(Stat.SPATK)).toBe(0); - expect(game.scene.getPlayerField()[0].species.speciesId).toBe(SpeciesId.MEOWTH); + expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.MURKROW); }, ); }); diff --git a/test/moves/reflect.test.ts b/test/moves/reflect.test.ts index b8fa2b1ce80..426027d3f31 100644 --- a/test/moves/reflect.test.ts +++ b/test/moves/reflect.test.ts @@ -19,7 +19,7 @@ describe("Moves - Reflect", () => { let phaserGame: Phaser.Game; let game: GameManager; const singleBattleMultiplier = 0.5; - const doubleBattleMultiplier = 2732 / 4096; + const doubleBattleMultiplier = 2 / 3; beforeAll(() => { phaserGame = new Phaser.Game({ diff --git a/test/moves/rest.test.ts b/test/moves/rest.test.ts new file mode 100644 index 00000000000..9f29d468e4a --- /dev/null +++ b/test/moves/rest.test.ts @@ -0,0 +1,146 @@ +import { AbilityId } from "#enums/ability-id"; +import { BattlerTagType } from "#enums/battler-tag-type"; +import { MoveId } from "#enums/move-id"; +import { MoveResult } from "#enums/move-result"; +import { SpeciesId } from "#enums/species-id"; +import { Stat } from "#enums/stat"; +import { StatusEffect } from "#enums/status-effect"; +import { GameManager } from "#test/test-utils/game-manager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Move - Rest", () => { + 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(AbilityId.BALL_FETCH) + .battleStyle("single") + .criticalHits(false) + .enemySpecies(SpeciesId.EKANS) + .enemyAbility(AbilityId.BALL_FETCH) + .enemyMoveset(MoveId.SPLASH); + }); + + it("should fully heal the user, cure its prior status and put it to sleep", async () => { + game.override.statusEffect(StatusEffect.POISON); + await game.classicMode.startBattle([SpeciesId.SNORLAX]); + + const snorlax = game.field.getPlayerPokemon(); + snorlax.hp = 1; + expect(snorlax.status?.effect).toBe(StatusEffect.POISON); + + game.move.use(MoveId.REST); + await game.toEndOfTurn(); + + expect(snorlax.hp).toBe(snorlax.getMaxHp()); + expect(snorlax.status?.effect).toBe(StatusEffect.SLEEP); + }); + + it("should always last 3 turns", async () => { + await game.classicMode.startBattle([SpeciesId.SNORLAX]); + + const snorlax = game.field.getPlayerPokemon(); + snorlax.hp = 1; + + // Cf https://bulbapedia.bulbagarden.net/wiki/Rest_(move): + // > The user is unable to use MoveId while asleep for 2 turns after the turn when Rest is used. + game.move.use(MoveId.REST); + await game.toNextTurn(); + + expect(snorlax.status?.effect).toBe(StatusEffect.SLEEP); + expect(snorlax.status?.sleepTurnsRemaining).toBe(3); + + game.move.use(MoveId.SWORDS_DANCE); + await game.toNextTurn(); + expect(snorlax.status?.sleepTurnsRemaining).toBe(2); + + game.move.use(MoveId.SWORDS_DANCE); + await game.toNextTurn(); + expect(snorlax.status?.sleepTurnsRemaining).toBe(1); + + game.move.use(MoveId.SWORDS_DANCE); + await game.toNextTurn(); + expect(snorlax.status?.effect).toBeUndefined(); + expect(snorlax.getStatStage(Stat.ATK)).toBe(2); + }); + + it("should preserve non-volatile status conditions", async () => { + await game.classicMode.startBattle([SpeciesId.SNORLAX]); + + const snorlax = game.field.getPlayerPokemon(); + snorlax.hp = 1; + snorlax.addTag(BattlerTagType.CONFUSED, 999); + + game.move.use(MoveId.REST); + await game.toEndOfTurn(); + + expect(snorlax.getTag(BattlerTagType.CONFUSED)).toBeDefined(); + }); + + it.each<{ name: string; status?: StatusEffect; ability?: AbilityId; dmg?: number }>([ + { name: "is at full HP", dmg: 0 }, + { name: "is grounded on Electric Terrain", ability: AbilityId.ELECTRIC_SURGE }, + { name: "is grounded on Misty Terrain", ability: AbilityId.MISTY_SURGE }, + { name: "has Comatose", ability: AbilityId.COMATOSE }, + ])("should fail if the user $name", async ({ status = StatusEffect.NONE, ability = AbilityId.NONE, dmg = 1 }) => { + game.override.ability(ability).statusEffect(status); + await game.classicMode.startBattle([SpeciesId.SNORLAX]); + + const snorlax = game.field.getPlayerPokemon(); + + snorlax.hp = snorlax.getMaxHp() - dmg; + + game.move.use(MoveId.REST); + await game.toEndOfTurn(); + + expect(snorlax.getLastXMoves()[0].result).toBe(MoveResult.FAIL); + }); + + it("should fail if called while already asleep", async () => { + game.override.statusEffect(StatusEffect.SLEEP).moveset([MoveId.REST, MoveId.SLEEP_TALK]); + await game.classicMode.startBattle([SpeciesId.SNORLAX]); + + const snorlax = game.field.getPlayerPokemon(); + snorlax.hp = 1; + + // Need to use sleep talk here since you normally can't move while asleep + game.move.select(MoveId.SLEEP_TALK); + await game.toEndOfTurn(); + + expect(snorlax.isFullHp()).toBe(false); + expect(snorlax.status?.effect).toBe(StatusEffect.SLEEP); + expect(snorlax.getLastXMoves(-1).map(tm => tm.result)).toEqual([MoveResult.FAIL, MoveResult.SUCCESS]); + }); + + it("should succeed if called the same turn as the user wakes", async () => { + game.override.statusEffect(StatusEffect.SLEEP); + await game.classicMode.startBattle([SpeciesId.SNORLAX]); + + const snorlax = game.field.getPlayerPokemon(); + snorlax.hp = 1; + + expect(snorlax.status?.effect).toBe(StatusEffect.SLEEP); + snorlax.status!.sleepTurnsRemaining = 1; + + game.move.use(MoveId.REST); + await game.toNextTurn(); + + expect(snorlax.status!.effect).toBe(StatusEffect.SLEEP); + expect(snorlax.isFullHp()).toBe(true); + expect(snorlax.getLastXMoves()[0].result).toBe(MoveResult.SUCCESS); + expect(snorlax.status!.sleepTurnsRemaining).toBeGreaterThan(1); + }); +}); diff --git a/test/moves/revival-blessing.test.ts b/test/moves/revival-blessing.test.ts index d14fa89c738..4dc7cb97f2d 100644 --- a/test/moves/revival-blessing.test.ts +++ b/test/moves/revival-blessing.test.ts @@ -133,6 +133,6 @@ describe("Moves - Revival Blessing", () => { await game.toNextTurn(); // If there are incorrectly two switch phases into this slot, the fainted pokemon will end up in slot 3 // Make sure it's still in slot 1 - expect(game.scene.getEnemyParty()[0]).toBe(enemyFainting); + expect(game.field.getEnemyPokemon()).toBe(enemyFainting); }); }); diff --git a/test/moves/rollout.test.ts b/test/moves/rollout.test.ts index c1c66f4ab39..0e01725a188 100644 --- a/test/moves/rollout.test.ts +++ b/test/moves/rollout.test.ts @@ -44,10 +44,10 @@ describe("Moves - Rollout", () => { await game.classicMode.startBattle(); - const playerPkm = game.scene.getPlayerParty()[0]; + const playerPkm = game.field.getPlayerPokemon(); vi.spyOn(playerPkm, "stats", "get").mockReturnValue([500000, 1, 1, 1, 1, 1]); // HP, ATK, DEF, SPATK, SPDEF, SPD - const enemyPkm = game.scene.getEnemyParty()[0]; + const enemyPkm = game.field.getEnemyPokemon(); 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 diff --git a/test/moves/sketch.test.ts b/test/moves/sketch.test.ts index ed010b8a883..0c2527bc09c 100644 --- a/test/moves/sketch.test.ts +++ b/test/moves/sketch.test.ts @@ -6,7 +6,6 @@ import { MoveResult } from "#enums/move-result"; import { SpeciesId } from "#enums/species-id"; import { StatusEffect } from "#enums/status-effect"; import { RandomMoveAttr } from "#moves/move"; -import { PokemonMove } from "#moves/pokemon-move"; import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; @@ -40,7 +39,7 @@ describe("Moves - Sketch", () => { await game.classicMode.startBattle([SpeciesId.REGIELEKI]); const playerPokemon = game.field.getPlayerPokemon(); // can't use normal moveset override because we need to check moveset changes - playerPokemon.moveset = [new PokemonMove(MoveId.SKETCH), new PokemonMove(MoveId.SKETCH)]; + game.move.changeMoveset(playerPokemon, [MoveId.SKETCH, MoveId.SKETCH]); game.move.select(MoveId.SKETCH); await game.phaseInterceptor.to("TurnEndPhase"); @@ -62,7 +61,7 @@ describe("Moves - Sketch", () => { await game.classicMode.startBattle([SpeciesId.REGIELEKI]); const playerPokemon = game.field.getPlayerPokemon(); const enemyPokemon = game.field.getEnemyPokemon(); - playerPokemon.moveset = [new PokemonMove(MoveId.SKETCH), new PokemonMove(MoveId.GROWL)]; + game.move.changeMoveset(playerPokemon, [MoveId.SKETCH, MoveId.GROWL]); game.move.select(MoveId.GROWL); await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); @@ -88,8 +87,9 @@ describe("Moves - Sketch", () => { game.override.enemyMoveset([MoveId.METRONOME]); await game.classicMode.startBattle([SpeciesId.REGIELEKI]); + const playerPokemon = game.field.getPlayerPokemon(); - playerPokemon.moveset = [new PokemonMove(MoveId.SKETCH)]; + game.move.changeMoveset(playerPokemon, MoveId.SKETCH); // Opponent uses Metronome -> False Swipe, then player uses Sketch, which should sketch Metronome game.move.select(MoveId.SKETCH); diff --git a/test/moves/sleep-talk.test.ts b/test/moves/sleep-talk.test.ts index 9e8db2e3615..56dc7ba2121 100644 --- a/test/moves/sleep-talk.test.ts +++ b/test/moves/sleep-talk.test.ts @@ -1,6 +1,7 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { MoveResult } from "#enums/move-result"; +import { MoveUseMode } from "#enums/move-use-mode"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#enums/stat"; import { StatusEffect } from "#enums/status-effect"; @@ -31,13 +32,36 @@ describe("Moves - Sleep Talk", () => { .battleStyle("single") .criticalHits(false) .enemySpecies(SpeciesId.MAGIKARP) - .enemyAbility(AbilityId.BALL_FETCH) + .enemyAbility(AbilityId.NO_GUARD) .enemyMoveset(MoveId.SPLASH) .enemyLevel(100); }); - it("should fail when the user is not asleep", async () => { - game.override.statusEffect(StatusEffect.NONE); + it("should call a random valid move if the user is asleep", async () => { + game.override.moveset([MoveId.SLEEP_TALK, MoveId.DIG, MoveId.FLY, MoveId.SWORDS_DANCE]); // Dig and Fly are invalid moves, Swords Dance should always be called + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + + game.move.select(MoveId.SLEEP_TALK); + await game.toNextTurn(); + + const feebas = game.field.getPlayerPokemon(); + expect(feebas.getStatStage(Stat.ATK)).toBe(2); + expect(feebas.getLastXMoves(2)).toEqual([ + expect.objectContaining({ + move: MoveId.SWORDS_DANCE, + result: MoveResult.SUCCESS, + useMode: MoveUseMode.FOLLOW_UP, + }), + expect.objectContaining({ + move: MoveId.SLEEP_TALK, + result: MoveResult.SUCCESS, + useMode: MoveUseMode.NORMAL, + }), + ]); + }); + + it("should fail if the user is not asleep", async () => { + game.override.statusEffect(StatusEffect.POISON); await game.classicMode.startBattle([SpeciesId.FEEBAS]); game.move.select(MoveId.SLEEP_TALK); @@ -45,6 +69,19 @@ describe("Moves - Sleep Talk", () => { expect(game.field.getPlayerPokemon().getLastXMoves()[0].result).toBe(MoveResult.FAIL); }); + it("should fail the turn the user wakes up from Sleep", async () => { + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + + const feebas = game.field.getPlayerPokemon(); + expect(feebas.status?.effect).toBe(StatusEffect.SLEEP); + feebas.status!.sleepTurnsRemaining = 1; + + game.move.select(MoveId.SLEEP_TALK); + await game.toNextTurn(); + + expect(feebas).toHaveUsedMove({ result: MoveResult.FAIL }); + }); + it("should fail if the user has no valid moves", async () => { game.override.moveset([MoveId.SLEEP_TALK, MoveId.DIG, MoveId.METRONOME, MoveId.SOLAR_BEAM]); await game.classicMode.startBattle([SpeciesId.FEEBAS]); @@ -54,22 +91,15 @@ describe("Moves - Sleep Talk", () => { expect(game.field.getPlayerPokemon().getLastXMoves()[0].result).toBe(MoveResult.FAIL); }); - it("should call a random valid move if the user is asleep", async () => { - game.override.moveset([MoveId.SLEEP_TALK, MoveId.DIG, MoveId.FLY, MoveId.SWORDS_DANCE]); // Dig and Fly are invalid moves, Swords Dance should always be called + it("should apply secondary effects of the called move", async () => { + game.override.moveset([MoveId.SLEEP_TALK, MoveId.SCALE_SHOT]); await game.classicMode.startBattle([SpeciesId.FEEBAS]); game.move.select(MoveId.SLEEP_TALK); await game.toNextTurn(); - expect(game.field.getPlayerPokemon().getStatStage(Stat.ATK)); - }); - it("should apply secondary effects of a move", async () => { - game.override.moveset([MoveId.SLEEP_TALK, MoveId.DIG, MoveId.FLY, MoveId.WOOD_HAMMER]); // Dig and Fly are invalid moves, Wood Hammer should always be called - await game.classicMode.startBattle(); - - game.move.select(MoveId.SLEEP_TALK); - await game.toNextTurn(); - - expect(game.field.getPlayerPokemon().isFullHp()).toBeFalsy(); // Wood Hammer recoil effect should be applied + const feebas = game.field.getPlayerPokemon(); + expect(feebas.getStatStage(Stat.SPD)).toBe(1); + expect(feebas.getStatStage(Stat.DEF)).toBe(-1); }); }); diff --git a/test/moves/spikes.test.ts b/test/moves/spikes.test.ts deleted file mode 100644 index 0055945cef9..00000000000 --- a/test/moves/spikes.test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { ArenaTrapTag } from "#data/arena-tag"; -import { AbilityId } from "#enums/ability-id"; -import { ArenaTagSide } from "#enums/arena-tag-side"; -import { BattlerIndex } from "#enums/battler-index"; -import { MoveId } from "#enums/move-id"; -import { SpeciesId } from "#enums/species-id"; -import { GameManager } from "#test/test-utils/game-manager"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -describe("Moves - 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 - .battleStyle("single") - .enemySpecies(SpeciesId.MAGIKARP) - .enemyAbility(AbilityId.BALL_FETCH) - .ability(AbilityId.BALL_FETCH) - .enemyMoveset(MoveId.SPLASH) - .moveset([MoveId.SPIKES, MoveId.SPLASH, MoveId.ROAR]); - }); - - it("should not damage the team that set them", async () => { - await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]); - - game.move.select(MoveId.SPIKES); - await game.toNextTurn(); - - game.move.select(MoveId.SPLASH); - await game.toNextTurn(); - - game.doSwitchPokemon(1); - await game.toNextTurn(); - - game.doSwitchPokemon(1); - await game.toNextTurn(); - - const player = game.scene.getPlayerParty()[0]; - expect(player.hp).toBe(player.getMaxHp()); - }); - - it("should damage opposing pokemon that are forced to switch in", async () => { - game.override.startingWave(5); - await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]); - - game.move.select(MoveId.SPIKES); - await game.toNextTurn(); - - game.move.select(MoveId.ROAR); - await game.toNextTurn(); - - const enemy = game.scene.getEnemyParty()[0]; - expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); - }); - - it("should damage opposing pokemon that choose to switch in", async () => { - game.override.startingWave(5); - await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]); - - game.move.select(MoveId.SPIKES); - await game.toNextTurn(); - - game.move.select(MoveId.SPLASH); - game.forceEnemyToSwitch(); - await game.toNextTurn(); - - const enemy = game.scene.getEnemyParty()[0]; - expect(enemy.hp).toBeLessThan(enemy.getMaxHp()); - }); - - // TODO: re-enable after re-fixing hazards moves - it.todo("should work when all targets fainted", async () => { - game.override.enemySpecies(SpeciesId.DIGLETT).battleStyle("double").startingLevel(1000); - await game.classicMode.startBattle([SpeciesId.RAYQUAZA, SpeciesId.SHUCKLE]); - - const [enemy1, enemy2] = game.scene.getEnemyField(); - - game.move.use(MoveId.HYPER_VOICE, BattlerIndex.PLAYER); - game.move.use(MoveId.SPIKES, BattlerIndex.PLAYER_2); - await game.toEndOfTurn(); - - expect(enemy1.isFainted()).toBe(true); - expect(enemy2.isFainted()).toBe(true); - expect(game.scene.arena.getTagOnSide(ArenaTrapTag, ArenaTagSide.ENEMY)).toBeDefined(); - }); -}); diff --git a/test/moves/tackle.test.ts b/test/moves/tackle.test.ts index 23abd650e55..5418b16bba8 100644 --- a/test/moves/tackle.test.ts +++ b/test/moves/tackle.test.ts @@ -1,8 +1,6 @@ import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#enums/stat"; -import { EnemyCommandPhase } from "#phases/enemy-command-phase"; -import { TurnEndPhase } from "#phases/turn-end-phase"; import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -41,7 +39,7 @@ describe("Moves - Tackle", () => { await game.classicMode.startBattle([SpeciesId.MIGHTYENA]); const hpOpponent = game.scene.currentBattle.enemyParty[0].hp; game.move.select(moveToUse); - await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase); + await game.toEndOfTurn(); const hpLost = hpOpponent - game.scene.currentBattle.enemyParty[0].hp; expect(hpLost).toBe(0); }); @@ -50,12 +48,12 @@ describe("Moves - Tackle", () => { const moveToUse = MoveId.TACKLE; await game.classicMode.startBattle([SpeciesId.MIGHTYENA]); game.scene.currentBattle.enemyParty[0].stats[Stat.DEF] = 50; - game.scene.getPlayerParty()[0].stats[Stat.ATK] = 50; + game.field.getPlayerPokemon().stats[Stat.ATK] = 50; const hpOpponent = game.scene.currentBattle.enemyParty[0].hp; game.move.select(moveToUse); - await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnEndPhase); + await game.toEndOfTurn(); const hpLost = hpOpponent - game.scene.currentBattle.enemyParty[0].hp; expect(hpLost).toBeGreaterThan(0); expect(hpLost).toBeLessThan(4); diff --git a/test/moves/tail-whip.test.ts b/test/moves/tail-whip.test.ts index 8d2dfbda096..70476179b03 100644 --- a/test/moves/tail-whip.test.ts +++ b/test/moves/tail-whip.test.ts @@ -2,8 +2,6 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#enums/stat"; -import { EnemyCommandPhase } from "#phases/enemy-command-phase"; -import { TurnInitPhase } from "#phases/turn-init-phase"; import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -43,7 +41,7 @@ describe("Moves - Tail whip", () => { expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(0); game.move.select(moveToUse); - await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase); + await game.toEndOfTurn(); expect(enemyPokemon.getStatStage(Stat.DEF)).toBe(-1); }); diff --git a/test/moves/tera-starstorm.test.ts b/test/moves/tera-starstorm.test.ts index 869cf597dde..178827c6b0a 100644 --- a/test/moves/tera-starstorm.test.ts +++ b/test/moves/tera-starstorm.test.ts @@ -72,7 +72,7 @@ describe("Moves - Tera Starstorm", () => { it("targets both opponents in a double battle when used by Terapagos immediately after terastallizing", async () => { await game.classicMode.startBattle([SpeciesId.TERAPAGOS]); - const terapagos = game.scene.getPlayerParty()[0]; + const terapagos = game.field.getPlayerPokemon(); terapagos.isTerastallized = false; game.move.selectWithTera(MoveId.TERA_STARSTORM, 0); @@ -89,7 +89,7 @@ describe("Moves - Tera Starstorm", () => { it("targets only one opponent in a double battle when used by Terapagos without terastallizing", async () => { await game.classicMode.startBattle([SpeciesId.TERAPAGOS]); - const terapagos = game.scene.getPlayerParty()[0]; + const terapagos = game.field.getPlayerPokemon(); terapagos.isTerastallized = false; game.move.select(MoveId.TERA_STARSTORM, 0, BattlerIndex.ENEMY); @@ -106,8 +106,7 @@ describe("Moves - Tera Starstorm", () => { it("applies the effects when Terapagos in Stellar Form is fused with another Pokemon", async () => { await game.classicMode.startBattle([SpeciesId.TERAPAGOS, SpeciesId.CHARMANDER, SpeciesId.MAGIKARP]); - const fusionedMon = game.scene.getPlayerParty()[0]; - const magikarp = game.scene.getPlayerParty()[2]; + const [fusionedMon, , magikarp] = game.scene.getPlayerParty(); // Fuse party members (taken from PlayerPokemon.fuse(...) function) fusionedMon.fusionSpecies = magikarp.species; diff --git a/test/moves/toxic-spikes.test.ts b/test/moves/toxic-spikes.test.ts deleted file mode 100644 index 0a0bf8baefc..00000000000 --- a/test/moves/toxic-spikes.test.ts +++ /dev/null @@ -1,143 +0,0 @@ -import type { ArenaTrapTag } from "#data/arena-tag"; -import { AbilityId } from "#enums/ability-id"; -import { ArenaTagSide } from "#enums/arena-tag-side"; -import { ArenaTagType } from "#enums/arena-tag-type"; -import { MoveId } from "#enums/move-id"; -import { SpeciesId } from "#enums/species-id"; -import { StatusEffect } from "#enums/status-effect"; -import type { SessionSaveData } from "#system/game-data"; -import { GameData } from "#system/game-data"; -import { GameManager } from "#test/test-utils/game-manager"; -import { decrypt, encrypt } from "#utils/data"; -import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; - -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 - .battleStyle("single") - .startingWave(5) - .enemySpecies(SpeciesId.RATTATA) - .enemyAbility(AbilityId.BALL_FETCH) - .ability(AbilityId.BALL_FETCH) - .enemyMoveset(MoveId.SPLASH) - .moveset([MoveId.TOXIC_SPIKES, MoveId.SPLASH, MoveId.ROAR, MoveId.COURT_CHANGE]); - }); - - it("should not affect the opponent if they do not switch", async () => { - await game.classicMode.runToSummon([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]); - - const enemy = game.scene.getEnemyField()[0]; - - game.move.select(MoveId.TOXIC_SPIKES); - await game.phaseInterceptor.to("TurnEndPhase"); - game.move.select(MoveId.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(); - }); - - it("should poison the opponent if they switch into 1 layer", async () => { - await game.classicMode.runToSummon([SpeciesId.MIGHTYENA]); - - game.move.select(MoveId.TOXIC_SPIKES); - await game.phaseInterceptor.to("TurnEndPhase"); - game.move.select(MoveId.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); - }); - - it("should badly poison the opponent if they switch into 2 layers", async () => { - await game.classicMode.runToSummon([SpeciesId.MIGHTYENA]); - - game.move.select(MoveId.TOXIC_SPIKES); - await game.phaseInterceptor.to("TurnEndPhase"); - game.move.select(MoveId.TOXIC_SPIKES); - await game.phaseInterceptor.to("TurnEndPhase"); - game.move.select(MoveId.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); - }); - - it("should be removed if a grounded poison pokemon switches in", async () => { - await game.classicMode.runToSummon([SpeciesId.MUK, SpeciesId.PIDGEY]); - - const muk = game.field.getPlayerPokemon(); - - game.move.select(MoveId.TOXIC_SPIKES); - await game.toNextTurn(); - // also make sure the toxic spikes are removed even if the pokemon - // that set them up is the one switching in (https://github.com/pagefaultgames/pokerogue/issues/935) - game.move.select(MoveId.COURT_CHANGE); - await game.toNextTurn(); - game.doSwitchPokemon(1); - await game.toNextTurn(); - game.doSwitchPokemon(1); - await game.toNextTurn(); - game.move.select(MoveId.SPLASH); - await game.toNextTurn(); - - expect(muk.isFullHp()).toBe(true); - expect(muk.status?.effect).toBeUndefined(); - expect(game.scene.arena.tags.length).toBe(0); - }); - - it("shouldn't create multiple layers per use in doubles", async () => { - await game.classicMode.runToSummon([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]); - - game.move.select(MoveId.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); - }); - - it("should persist through reload", async () => { - game.override.startingWave(1); - const gameData = new GameData(); - - await game.classicMode.runToSummon([SpeciesId.MIGHTYENA]); - - game.move.select(MoveId.TOXIC_SPIKES); - await game.phaseInterceptor.to("TurnEndPhase"); - game.move.select(MoveId.SPLASH); - await game.doKillOpponents(); - await game.phaseInterceptor.to("BattleEndPhase"); - await game.toNextWave(); - - const sessionData: SessionSaveData = gameData.getSessionSaveData(); - localStorage.setItem("sessionTestData", encrypt(JSON.stringify(sessionData), true)); - const recoveredData: SessionSaveData = gameData.parseSessionData( - decrypt(localStorage.getItem("sessionTestData")!, true), - ); - await gameData.loadSession(0, recoveredData); - - expect(sessionData.arena.tags).toEqual(recoveredData.arena.tags); - localStorage.removeItem("sessionTestData"); - }); -}); diff --git a/test/moves/trick-room.test.ts b/test/moves/trick-room.test.ts new file mode 100644 index 00000000000..a1d81efb17e --- /dev/null +++ b/test/moves/trick-room.test.ts @@ -0,0 +1,82 @@ +import { AbilityId } from "#enums/ability-id"; +import { ArenaTagSide } from "#enums/arena-tag-side"; +import { ArenaTagType } from "#enums/arena-tag-type"; +import { BattlerIndex } from "#enums/battler-index"; +import { MoveId } from "#enums/move-id"; +import { SpeciesId } from "#enums/species-id"; +import { Stat } from "#enums/stat"; +import { TurnStartPhase } from "#phases/turn-start-phase"; +import { GameManager } from "#test/test-utils/game-manager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +describe("Move - Trick Room", () => { + 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(AbilityId.BALL_FETCH) + .battleStyle("single") + .criticalHits(false) + .enemySpecies(SpeciesId.MAGIKARP) + .enemyAbility(AbilityId.BALL_FETCH) + .enemyMoveset(MoveId.SPLASH); + }); + + it("should reverse the speed order of combatants while active", async () => { + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + + const feebas = game.field.getPlayerPokemon(); + const karp = game.field.getEnemyPokemon(); + feebas.setStat(Stat.SPD, 2); + karp.setStat(Stat.SPD, 1); + expect(game.field.getSpeedOrder(true)).toEqual([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); + + // Add trick room to the field + game.move.use(MoveId.TRICK_ROOM); + await game.toNextTurn(); + + expect(game).toHaveArenaTag({ + tagType: ArenaTagType.TRICK_ROOM, + side: ArenaTagSide.BOTH, + sourceId: feebas.id, + sourceMove: MoveId.TRICK_ROOM, + turnCount: 4, // The 5 turn limit _includes_ the current turn! + }); + + // Now, check that speed was indeed reduced + const turnOrderSpy = vi.spyOn(TurnStartPhase.prototype, "getSpeedOrder"); + + game.move.use(MoveId.SPLASH); + await game.toEndOfTurn(); + + expect(turnOrderSpy).toHaveLastReturnedWith([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + }); + + it("should be removed when overlapped", async () => { + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + + const feebas = game.field.getPlayerPokemon(); + + // Add trick room to the field, then add it again! + game.scene.arena.addTag(ArenaTagType.TRICK_ROOM, 5, MoveId.TRICK_ROOM, feebas.id); + + expect(game).toHaveArenaTag(ArenaTagType.TRICK_ROOM); + + game.scene.arena.addTag(ArenaTagType.TRICK_ROOM, 5, MoveId.TRICK_ROOM, feebas.id); + + expect(game).not.toHaveArenaTag(ArenaTagType.TRICK_ROOM); + }); +}); diff --git a/test/mystery-encounter/encounter-test-utils.ts b/test/mystery-encounter/encounter-test-utils.ts index 784e8ae4950..7b2dbfc9aeb 100644 --- a/test/mystery-encounter/encounter-test-utils.ts +++ b/test/mystery-encounter/encounter-test-utils.ts @@ -9,7 +9,6 @@ import { MessagePhase } from "#phases/message-phase"; import { MysteryEncounterBattlePhase, MysteryEncounterOptionSelectedPhase, - MysteryEncounterPhase, MysteryEncounterRewardsPhase, } from "#phases/mystery-encounter-phases"; import { VictoryPhase } from "#phases/victory-phase"; @@ -89,9 +88,9 @@ export async function runMysteryEncounterToEnd( uiHandler.processInput(Button.ACTION); }); - await game.phaseInterceptor.to(CommandPhase); + await game.toNextTurn(); } else { - await game.phaseInterceptor.to(MysteryEncounterRewardsPhase); + await game.phaseInterceptor.to("MysteryEncounterRewardsPhase"); } } @@ -112,7 +111,7 @@ export async function runSelectMysteryEncounterOption( ); if (game.isCurrentPhase(MessagePhase)) { - await game.phaseInterceptor.run(MessagePhase); + await game.phaseInterceptor.to("MessagePhase"); } // dispose of intro messages @@ -126,7 +125,7 @@ export async function runSelectMysteryEncounterOption( () => game.isCurrentPhase(MysteryEncounterOptionSelectedPhase), ); - await game.phaseInterceptor.to(MysteryEncounterPhase, true); + await game.phaseInterceptor.to("MysteryEncounterPhase", true); // select the desired option const uiHandler = game.scene.ui.getHandler(); @@ -205,7 +204,7 @@ export async function skipBattleRunMysteryEncounterRewardsPhase(game: GameManage game.scene.field.remove(p); }); game.scene.phaseManager.pushPhase(new VictoryPhase(0)); - game.phaseInterceptor.superEndPhase(); + game.endPhase(); game.setMode(UiMode.MESSAGE); - await game.phaseInterceptor.to(MysteryEncounterRewardsPhase, runRewardsPhase); + await game.phaseInterceptor.to("MysteryEncounterRewardsPhase", runRewardsPhase); } diff --git a/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts b/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts index d903568785a..9cd1679c411 100644 --- a/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts +++ b/test/mystery-encounter/encounters/an-offer-you-cant-refuse-encounter.test.ts @@ -7,7 +7,6 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { SpeciesId } from "#enums/species-id"; import { ShinyRateBoosterModifier } from "#modifiers/modifier"; -import { PokemonMove } from "#moves/pokemon-move"; import { AnOfferYouCantRefuseEncounter } from "#mystery-encounters/an-offer-you-cant-refuse-encounter"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; @@ -66,7 +65,7 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => { expect(AnOfferYouCantRefuseEncounter.dialogue).toBeDefined(); expect(AnOfferYouCantRefuseEncounter.dialogue.intro).toStrictEqual([ { text: `${namespace}:intro` }, - { speaker: `${namespace}:speaker`, text: `${namespace}:intro_dialogue` }, + { speaker: `${namespace}:speaker`, text: `${namespace}:introDialogue` }, ]); expect(AnOfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); expect(AnOfferYouCantRefuseEncounter.dialogue.encounterOptionsDialogue?.description).toBe( @@ -180,7 +179,7 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.tooltip_disabled`, + disabledButtonTooltip: `${namespace}:option.2.tooltipDisabled`, selected: [ { speaker: `${namespace}:speaker`, @@ -207,9 +206,8 @@ describe("An Offer You Can't Refuse - Mystery Encounter", () => { it("should award EXP to a pokemon with a move in EXTORTION_MOVES", async () => { game.override.ability(AbilityId.SYNCHRONIZE); // Not an extortion ability, so we can test extortion move await game.runToMysteryEncounter(MysteryEncounterType.AN_OFFER_YOU_CANT_REFUSE, [SpeciesId.ABRA]); - const party = scene.getPlayerParty(); - const abra = party.find(pkm => pkm.species.speciesId === SpeciesId.ABRA)!; - abra.moveset = [new PokemonMove(MoveId.BEAT_UP)]; + const abra = game.field.getPlayerPokemon(); + game.move.changeMoveset(abra, MoveId.BEAT_UP); const expBefore = abra.exp; await runMysteryEncounterToEnd(game, 2); diff --git a/test/mystery-encounter/encounters/berries-abound-encounter.test.ts b/test/mystery-encounter/encounters/berries-abound-encounter.test.ts index 25116a89ec5..12c5a6515bc 100644 --- a/test/mystery-encounter/encounters/berries-abound-encounter.test.ts +++ b/test/mystery-encounter/encounters/berries-abound-encounter.test.ts @@ -134,7 +134,7 @@ describe("Berries Abound - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); const berriesAfter = scene.findModifiers(m => m instanceof BerryModifier) as BerryModifier[]; @@ -147,9 +147,7 @@ describe("Berries Abound - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.BERRIES_ABOUND, defaultParty); await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -194,7 +192,7 @@ describe("Berries Abound - Mystery Encounter", () => { // Should be enraged expect(enemyField[0].summonData.statStages).toEqual([0, 1, 0, 1, 1, 0, 0]); - expect(encounterTextSpy).toHaveBeenCalledWith(`${namespace}:option.2.selected_bad`); + expect(encounterTextSpy).toHaveBeenCalledWith(`${namespace}:option.2.selectedBad`); }); it("should start battle if fastest pokemon is slower than boss above wave 50", async () => { @@ -218,7 +216,7 @@ describe("Berries Abound - Mystery Encounter", () => { // Should be enraged expect(enemyField[0].summonData.statStages).toEqual([1, 1, 1, 1, 1, 0, 0]); - expect(encounterTextSpy).toHaveBeenCalledWith(`${namespace}:option.2.selected_bad`); + expect(encounterTextSpy).toHaveBeenCalledWith(`${namespace}:option.2.selectedBad`); }); it("Should skip battle when fastest pokemon is faster than boss", async () => { @@ -232,9 +230,9 @@ describe("Berries Abound - Mystery Encounter", () => { }); await runMysteryEncounterToEnd(game, 2); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts b/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts index bed9d48d063..13d3c030c63 100644 --- a/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts +++ b/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts @@ -181,7 +181,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]); expect(BugTypeSuperfanEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); @@ -368,9 +368,9 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterRewardsPhase.name); game.phaseInterceptor["prompts"] = []; // Clear out prompt handlers game.onNextPrompt("MysteryEncounterRewardsPhase", UiMode.OPTION_SELECT, () => { - game.phaseInterceptor.superEndPhase(); + game.endPhase(); }); - await game.phaseInterceptor.run(MysteryEncounterRewardsPhase); + await game.phaseInterceptor.to("MysteryEncounterRewardsPhase"); expect(selectOptionSpy).toHaveBeenCalledTimes(1); const optionData = selectOptionSpy.mock.calls[0][0]; @@ -389,13 +389,13 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.2.disabledTooltip`, }); }); it("should NOT be selectable if the player doesn't have any Bug types", async () => { await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, [SpeciesId.ABRA]); - await game.phaseInterceptor.to(MysteryEncounterPhase, false); + await game.phaseInterceptor.to("MysteryEncounterPhase", false); const encounterPhase = scene.phaseManager.getCurrentPhase(); expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name); @@ -417,7 +417,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -436,7 +436,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -458,7 +458,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -482,7 +482,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -513,24 +513,24 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, selected: [ { text: `${namespace}:option.3.selected`, }, { speaker: `${namespace}:speaker`, - text: `${namespace}:option.3.selected_dialogue`, + text: `${namespace}:option.3.selectedDialogue`, }, ], - secondOptionPrompt: `${namespace}:option.3.select_prompt`, + secondOptionPrompt: `${namespace}:option.3.selectPrompt`, }); }); it("should NOT be selectable if the player doesn't have any Bug items", async () => { game.scene.modifiers = []; await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty); - await game.phaseInterceptor.to(MysteryEncounterPhase, false); + await game.phaseInterceptor.to("MysteryEncounterPhase", false); game.scene.modifiers = []; const encounterPhase = scene.phaseManager.getCurrentPhase(); @@ -558,7 +558,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/mystery-encounter/encounters/clowning-around-encounter.test.ts b/test/mystery-encounter/encounters/clowning-around-encounter.test.ts index b573701d568..f02a5c623af 100644 --- a/test/mystery-encounter/encounters/clowning-around-encounter.test.ts +++ b/test/mystery-encounter/encounters/clowning-around-encounter.test.ts @@ -25,7 +25,6 @@ import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { CommandPhase } from "#phases/command-phase"; import { MovePhase } from "#phases/move-phase"; import { PostMysteryEncounterPhase } from "#phases/mystery-encounter-phases"; -import { NewBattlePhase } from "#phases/new-battle-phase"; import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, @@ -80,7 +79,7 @@ describe("Clowning Around - Mystery Encounter", () => { { text: `${namespace}:intro` }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]); expect(ClowningAroundEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); @@ -200,9 +199,9 @@ describe("Clowning Around - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty); await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); const abilityToTrain = scene.currentBattle.mysteryEncounter?.misc.ability; game.onNextPrompt("PostMysteryEncounterPhase", UiMode.MESSAGE, () => { @@ -215,7 +214,7 @@ describe("Clowning Around - Mystery Encounter", () => { const partyUiHandler = game.scene.ui.handlers[UiMode.PARTY] as PartyUiHandler; vi.spyOn(partyUiHandler, "show"); game.endPhase(); - await game.phaseInterceptor.to(PostMysteryEncounterPhase); + await game.phaseInterceptor.to("PostMysteryEncounterPhase"); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(PostMysteryEncounterPhase.name); // Wait for Yes/No confirmation to appear @@ -228,9 +227,9 @@ describe("Clowning Around - Mystery Encounter", () => { // Click "Select" on Pokemon partyUiHandler.processInput(Button.ACTION); // Stop next battle before it runs - await game.phaseInterceptor.to(NewBattlePhase, false); + await game.phaseInterceptor.to("NewBattlePhase", false); - const leadPokemon = scene.getPlayerParty()[0]; + const leadPokemon = game.field.getPlayerPokemon(); expect(leadPokemon.customPokemonData?.ability).toBe(abilityToTrain); }); }); @@ -249,11 +248,11 @@ describe("Clowning Around - Mystery Encounter", () => { text: `${namespace}:option.2.selected`, }, { - text: `${namespace}:option.2.selected_2`, + text: `${namespace}:option.2.selected2`, }, { speaker: `${namespace}:speaker`, - text: `${namespace}:option.2.selected_3`, + text: `${namespace}:option.2.selected3`, }, ], }); @@ -263,30 +262,30 @@ describe("Clowning Around - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty); // Set some moves on party for attack type booster generation - scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.TACKLE), new PokemonMove(MoveId.THIEF)]; + game.move.changeMoveset(game.field.getPlayerPokemon(), [MoveId.TACKLE, MoveId.THIEF]); // 2 Sitrus Berries on lead scene.modifiers = []; let itemType = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS]) as PokemonHeldItemModifierType; - await addItemToPokemon(scene, scene.getPlayerParty()[0], 2, itemType); + await addItemToPokemon(scene, game.field.getPlayerPokemon(), 2, itemType); // 2 Ganlon Berries on lead itemType = generateModifierType(modifierTypes.BERRY, [BerryType.GANLON]) as PokemonHeldItemModifierType; - await addItemToPokemon(scene, scene.getPlayerParty()[0], 2, itemType); + await addItemToPokemon(scene, game.field.getPlayerPokemon(), 2, itemType); // 5 Golden Punch on lead (ultra) itemType = generateModifierType(modifierTypes.GOLDEN_PUNCH) as PokemonHeldItemModifierType; - await addItemToPokemon(scene, scene.getPlayerParty()[0], 5, itemType); + await addItemToPokemon(scene, game.field.getPlayerPokemon(), 5, itemType); // 5 Lucky Egg on lead (ultra) itemType = generateModifierType(modifierTypes.LUCKY_EGG) as PokemonHeldItemModifierType; - await addItemToPokemon(scene, scene.getPlayerParty()[0], 5, itemType); + await addItemToPokemon(scene, game.field.getPlayerPokemon(), 5, itemType); // 3 Soothe Bell on lead (great tier, but counted as ultra by this ME) itemType = generateModifierType(modifierTypes.SOOTHE_BELL) as PokemonHeldItemModifierType; - await addItemToPokemon(scene, scene.getPlayerParty()[0], 3, itemType); + await addItemToPokemon(scene, game.field.getPlayerPokemon(), 3, itemType); // 5 Soul Dew on lead (rogue) itemType = generateModifierType(modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType; - await addItemToPokemon(scene, scene.getPlayerParty()[0], 5, itemType); + await addItemToPokemon(scene, game.field.getPlayerPokemon(), 5, itemType); // 2 Golden Egg on lead (rogue) itemType = generateModifierType(modifierTypes.GOLDEN_EGG) as PokemonHeldItemModifierType; - await addItemToPokemon(scene, scene.getPlayerParty()[0], 2, itemType); + await addItemToPokemon(scene, game.field.getPlayerPokemon(), 2, itemType); // 5 Soul Dew on second party pokemon (these should not change) itemType = generateModifierType(modifierTypes.SOUL_DEW) as PokemonHeldItemModifierType; @@ -294,7 +293,7 @@ describe("Clowning Around - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2); - const leadItemsAfter = scene.getPlayerParty()[0].getHeldItems(); + const leadItemsAfter = game.field.getPlayerPokemon().getHeldItems(); const ultraCountAfter = leadItemsAfter .filter(m => m.type.tier === ModifierTier.ULTRA) .reduce((a, b) => a + b.stackCount, 0); @@ -334,11 +333,11 @@ describe("Clowning Around - Mystery Encounter", () => { text: `${namespace}:option.3.selected`, }, { - text: `${namespace}:option.3.selected_2`, + text: `${namespace}:option.3.selected2`, }, { speaker: `${namespace}:speaker`, - text: `${namespace}:option.3.selected_3`, + text: `${namespace}:option.3.selected3`, }, ], }); @@ -348,14 +347,14 @@ describe("Clowning Around - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.CLOWNING_AROUND, defaultParty); // Same type moves on lead - scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.ICE_BEAM), new PokemonMove(MoveId.SURF)]; + game.move.changeMoveset(game.field.getPlayerPokemon(), [MoveId.ICE_BEAM, MoveId.SURF]); // Different type moves on second - scene.getPlayerParty()[1].moveset = [new PokemonMove(MoveId.GRASS_KNOT), new PokemonMove(MoveId.ELECTRO_BALL)]; + game.move.changeMoveset(scene.getPlayerParty()[1], [MoveId.GRASS_KNOT, MoveId.ELECTRO_BALL]); // No moves on third scene.getPlayerParty()[2].moveset = []; await runMysteryEncounterToEnd(game, 3); - const leadTypesAfter = scene.getPlayerParty()[0].getTypes(); + const leadTypesAfter = game.field.getPlayerPokemon().getTypes(); const secondaryTypesAfter = scene.getPlayerParty()[1].getTypes(); const thirdTypesAfter = scene.getPlayerParty()[2].getTypes(); diff --git a/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts b/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts index 97d0ce31367..de47b074089 100644 --- a/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts +++ b/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts @@ -6,7 +6,6 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { SpeciesId } from "#enums/species-id"; import { UiMode } from "#enums/ui-mode"; -import { PokemonMove } from "#moves/pokemon-move"; import { DancingLessonsEncounter } from "#mystery-encounters/dancing-lessons-encounter"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; @@ -100,7 +99,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); // Make party lead's level arbitrarily high to not get KOed by move - const partyLead = scene.getPlayerParty()[0]; + const partyLead = game.field.getPlayerPokemon(); partyLead.level = 1000; partyLead.calculateStats(); await runMysteryEncounterToEnd(game, 1, undefined, true); @@ -121,14 +120,14 @@ describe("Dancing Lessons - Mystery Encounter", () => { it("should have a Baton in the rewards after battle", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); // Make party lead's level arbitrarily high to not get KOed by move - const partyLead = scene.getPlayerParty()[0]; + const partyLead = game.field.getPlayerPokemon(); partyLead.level = 1000; partyLead.calculateStats(); await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -159,7 +158,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { const phaseSpy = vi.spyOn(scene.phaseManager, "unshiftPhase"); await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); - scene.getPlayerParty()[0].moveset = []; + game.field.getPlayerPokemon().moveset = []; await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1 }); const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof LearnMovePhase).map(p => p[0]); @@ -171,7 +170,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); - scene.getPlayerParty()[0].moveset = []; + game.field.getPlayerPokemon().moveset = []; await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1 }); expect(leaveEncounterWithoutBattleSpy).toBeCalled(); @@ -186,8 +185,8 @@ describe("Dancing Lessons - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, - secondOptionPrompt: `${namespace}:option.3.select_prompt`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, + secondOptionPrompt: `${namespace}:option.3.selectPrompt`, selected: [ { text: `${namespace}:option.3.selected`, @@ -199,7 +198,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { it("should add Oricorio to the party", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); const partyCountBefore = scene.getPlayerParty().length; - scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.DRAGON_DANCE)]; + game.move.changeMoveset(game.field.getPlayerPokemon(), MoveId.DRAGON_DANCE); await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); const partyCountAfter = scene.getPlayerParty().length; @@ -215,7 +214,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); const partyCountBefore = scene.getPlayerParty().length; scene.getPlayerParty().forEach(p => (p.moveset = [])); - await game.phaseInterceptor.to(MysteryEncounterPhase, false); + await game.phaseInterceptor.to("MysteryEncounterPhase", false); const encounterPhase = scene.phaseManager.getCurrentPhase(); expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name); @@ -238,7 +237,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); await game.runToMysteryEncounter(MysteryEncounterType.DANCING_LESSONS, defaultParty); - scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.DRAGON_DANCE)]; + game.move.changeMoveset(game.field.getPlayerPokemon(), MoveId.DRAGON_DANCE); await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); expect(leaveEncounterWithoutBattleSpy).toBeCalled(); diff --git a/test/mystery-encounter/encounters/delibirdy-encounter.test.ts b/test/mystery-encounter/encounters/delibirdy-encounter.test.ts index 16c726f1de6..7398b639f1c 100644 --- a/test/mystery-encounter/encounters/delibirdy-encounter.test.ts +++ b/test/mystery-encounter/encounters/delibirdy-encounter.test.ts @@ -186,7 +186,7 @@ describe("Delibird-y - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - secondOptionPrompt: `${namespace}:option.2.select_prompt`, + secondOptionPrompt: `${namespace}:option.2.selectPrompt`, selected: [ { text: `${namespace}:option.2.selected`, @@ -201,7 +201,7 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 2 Sitrus berries on party lead scene.modifiers = []; const sitrus = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS])!; - const sitrusMod = sitrus.newModifier(scene.getPlayerParty()[0]) as BerryModifier; + const sitrusMod = sitrus.newModifier(game.field.getPlayerPokemon()) as BerryModifier; sitrusMod.stackCount = 2; scene.addModifier(sitrusMod, true, false, false, true); await scene.updateModifiers(true); @@ -222,7 +222,7 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 1 Reviver Seed on party lead scene.modifiers = []; const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!; - const modifier = revSeed.newModifier(scene.getPlayerParty()[0]) as PokemonInstantReviveModifier; + const modifier = revSeed.newModifier(game.field.getPlayerPokemon()) as PokemonInstantReviveModifier; modifier.stackCount = 1; scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); @@ -248,7 +248,7 @@ describe("Delibird-y - Mystery Encounter", () => { const sitrus = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS])!; // Sitrus berries on party - const sitrusMod = sitrus.newModifier(scene.getPlayerParty()[0]) as BerryModifier; + const sitrusMod = sitrus.newModifier(game.field.getPlayerPokemon()) as BerryModifier; sitrusMod.stackCount = 2; scene.addModifier(sitrusMod, true, false, false, true); await scene.updateModifiers(true); @@ -277,7 +277,7 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 1 Reviver Seed on party lead const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!; - const modifier = revSeed.newModifier(scene.getPlayerParty()[0]) as PokemonInstantReviveModifier; + const modifier = revSeed.newModifier(game.field.getPlayerPokemon()) as PokemonInstantReviveModifier; modifier.stackCount = 1; scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); @@ -301,7 +301,7 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 1 Soul Dew on party lead scene.modifiers = []; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; - const modifier = soulDew.newModifier(scene.getPlayerParty()[0]); + const modifier = soulDew.newModifier(game.field.getPlayerPokemon()); scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); @@ -329,7 +329,7 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 1 Reviver Seed on party lead const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!; - const modifier = revSeed.newModifier(scene.getPlayerParty()[0]) as PokemonInstantReviveModifier; + const modifier = revSeed.newModifier(game.field.getPlayerPokemon()) as PokemonInstantReviveModifier; modifier.stackCount = 1; scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); @@ -348,7 +348,7 @@ describe("Delibird-y - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - secondOptionPrompt: `${namespace}:option.3.select_prompt`, + secondOptionPrompt: `${namespace}:option.3.selectPrompt`, selected: [ { text: `${namespace}:option.3.selected`, @@ -363,7 +363,7 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 2 Soul Dew on party lead scene.modifiers = []; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; - const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; + const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier; modifier.stackCount = 2; scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); @@ -384,7 +384,7 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 1 Soul Dew on party lead scene.modifiers = []; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; - const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; + const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier; modifier.stackCount = 1; scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); @@ -410,7 +410,7 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 1 Soul Dew on party lead const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; - const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; + const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier; modifier.stackCount = 1; scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); @@ -434,7 +434,7 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 1 Reviver Seed on party lead scene.modifiers = []; const revSeed = generateModifierType(modifierTypes.REVIVER_SEED)!; - const modifier = revSeed.newModifier(scene.getPlayerParty()[0]); + const modifier = revSeed.newModifier(game.field.getPlayerPokemon()); scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); @@ -463,7 +463,7 @@ describe("Delibird-y - Mystery Encounter", () => { // Set 1 Soul Dew on party lead scene.modifiers = []; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; - const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; + const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier; modifier.stackCount = 1; scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); diff --git a/test/mystery-encounter/encounters/department-store-sale-encounter.test.ts b/test/mystery-encounter/encounters/department-store-sale-encounter.test.ts index 3d84d70b47e..3c19d458049 100644 --- a/test/mystery-encounter/encounters/department-store-sale-encounter.test.ts +++ b/test/mystery-encounter/encounters/department-store-sale-encounter.test.ts @@ -61,7 +61,7 @@ describe("Department Store Sale - Mystery Encounter", () => { { text: `${namespace}:intro` }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]); expect(DepartmentStoreSaleEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); @@ -94,7 +94,7 @@ describe("Department Store Sale - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty); await runMysteryEncounterToEnd(game, 1); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -131,7 +131,7 @@ describe("Department Store Sale - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty); await runMysteryEncounterToEnd(game, 2); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -171,7 +171,7 @@ describe("Department Store Sale - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty); await runMysteryEncounterToEnd(game, 3); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -211,7 +211,7 @@ describe("Department Store Sale - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty); await runMysteryEncounterToEnd(game, 4); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/mystery-encounter/encounters/field-trip-encounter.test.ts b/test/mystery-encounter/encounters/field-trip-encounter.test.ts index 8502137cc6e..fd3e20012b1 100644 --- a/test/mystery-encounter/encounters/field-trip-encounter.test.ts +++ b/test/mystery-encounter/encounters/field-trip-encounter.test.ts @@ -61,7 +61,7 @@ describe("Field Trip - Mystery Encounter", () => { }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]); expect(FieldTripEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); @@ -78,7 +78,7 @@ describe("Field Trip - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.1.label`, buttonTooltip: `${namespace}:option.1.tooltip`, - secondOptionPrompt: `${namespace}:second_option_prompt`, + secondOptionPrompt: `${namespace}:secondOptionPrompt`, }); }); @@ -139,7 +139,7 @@ describe("Field Trip - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - secondOptionPrompt: `${namespace}:second_option_prompt`, + secondOptionPrompt: `${namespace}:secondOptionPrompt`, }); }); @@ -200,7 +200,7 @@ describe("Field Trip - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - secondOptionPrompt: `${namespace}:second_option_prompt`, + secondOptionPrompt: `${namespace}:secondOptionPrompt`, }); }); diff --git a/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts b/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts index a48422c459f..54f790ca207 100644 --- a/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts +++ b/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts @@ -253,7 +253,7 @@ describe("Fiery Fallout - Mystery Encounter", () => { expect(option1.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, selected: [ { text: `${namespace}:option.3.selected`, diff --git a/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts b/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts index 8149212f00f..8650b42ce4d 100644 --- a/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts +++ b/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts @@ -6,7 +6,6 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { SpeciesId } from "#enums/species-id"; import { UiMode } from "#enums/ui-mode"; -import { PokemonMove } from "#moves/pokemon-move"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import { FightOrFlightEncounter } from "#mystery-encounters/fight-or-flight-encounter"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; @@ -122,9 +121,9 @@ describe("Fight or Flight - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -143,7 +142,7 @@ describe("Fight or Flight - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.2.disabledTooltip`, selected: [ { text: `${namespace}:option.2.selected`, @@ -155,7 +154,7 @@ describe("Fight or Flight - Mystery Encounter", () => { it("should NOT be selectable if the player doesn't have a Stealing move", async () => { await game.runToMysteryEncounter(MysteryEncounterType.FIGHT_OR_FLIGHT, defaultParty); scene.getPlayerParty().forEach(p => (p.moveset = [])); - await game.phaseInterceptor.to(MysteryEncounterPhase, false); + await game.phaseInterceptor.to("MysteryEncounterPhase", false); const encounterPhase = scene.phaseManager.getCurrentPhase(); expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name); @@ -178,13 +177,13 @@ describe("Fight or Flight - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.FIGHT_OR_FLIGHT, defaultParty); // Mock moveset - scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.KNOCK_OFF)]; + game.move.changeMoveset(game.field.getPlayerPokemon(), MoveId.KNOCK_OFF); const item = game.scene.currentBattle.mysteryEncounter!.misc; await runMysteryEncounterToEnd(game, 2); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts b/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts index 3025b08b8b6..7bfaaac1141 100644 --- a/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts +++ b/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts @@ -71,7 +71,7 @@ describe("Fun And Games! - Mystery Encounter", () => { expect(FunAndGamesEncounter.dialogue.intro).toStrictEqual([ { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]); expect(FunAndGamesEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); @@ -120,7 +120,7 @@ describe("Fun And Games! - Mystery Encounter", () => { it("should NOT be selectable if the player doesn't have enough money", async () => { game.scene.money = 0; await game.runToMysteryEncounter(MysteryEncounterType.FUN_AND_GAMES, defaultParty); - await game.phaseInterceptor.to(MysteryEncounterPhase, false); + await game.phaseInterceptor.to("MysteryEncounterPhase", false); const encounterPhase = scene.phaseManager.getCurrentPhase(); expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name); @@ -162,7 +162,7 @@ describe("Fun And Games! - Mystery Encounter", () => { // Turn 3 (game.scene.phaseManager.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, 0, MoveUseMode.NORMAL); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); // Rewards expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); @@ -181,11 +181,11 @@ describe("Fun And Games! - Mystery Encounter", () => { // Skip minigame scene.currentBattle.mysteryEncounter!.misc.turnsRemaining = 0; (game.scene.phaseManager.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, 0, MoveUseMode.NORMAL); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); // Rewards expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -210,11 +210,11 @@ describe("Fun And Games! - Mystery Encounter", () => { wobbuffet.hp = Math.floor(0.2 * wobbuffet.getMaxHp()); scene.currentBattle.mysteryEncounter!.misc.turnsRemaining = 0; (game.scene.phaseManager.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, 0, MoveUseMode.NORMAL); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); // Rewards expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -240,11 +240,11 @@ describe("Fun And Games! - Mystery Encounter", () => { wobbuffet.hp = Math.floor(0.1 * wobbuffet.getMaxHp()); scene.currentBattle.mysteryEncounter!.misc.turnsRemaining = 0; (game.scene.phaseManager.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, 0, MoveUseMode.NORMAL); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); // Rewards expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -270,11 +270,11 @@ describe("Fun And Games! - Mystery Encounter", () => { wobbuffet.hp = 1; scene.currentBattle.mysteryEncounter!.misc.turnsRemaining = 0; (game.scene.phaseManager.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, 0, MoveUseMode.NORMAL); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); // Rewards expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts b/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts index 867a33f6ab6..bb56505ac48 100644 --- a/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts +++ b/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts @@ -98,21 +98,21 @@ describe("Global Trade System - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.1.label`, buttonTooltip: `${namespace}:option.1.tooltip`, - secondOptionPrompt: `${namespace}:option.1.trade_options_prompt`, + secondOptionPrompt: `${namespace}:option.1.tradeOptionsPrompt`, }); }); it("Should trade a Pokemon from the player's party for the first of 3 Pokemon options", async () => { await game.runToMysteryEncounter(MysteryEncounterType.GLOBAL_TRADE_SYSTEM, defaultParty); - const speciesBefore = scene.getPlayerParty()[0].species.speciesId; + const speciesBefore = game.field.getPlayerPokemon().species.speciesId; await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1, optionNo: 1 }); const speciesAfter = scene.getPlayerParty().at(-1)?.species.speciesId; expect(speciesAfter).toBeDefined(); expect(speciesBefore).not.toBe(speciesAfter); - expect(defaultParty.includes(speciesAfter!)).toBeFalsy(); + expect(defaultParty).not.toContain(speciesAfter); }); it("Should trade a Pokemon from the player's party for the second of 3 Pokemon options", async () => { @@ -210,7 +210,7 @@ describe("Global Trade System - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - secondOptionPrompt: `${namespace}:option.3.trade_options_prompt`, + secondOptionPrompt: `${namespace}:option.3.tradeOptionsPrompt`, }); }); @@ -220,14 +220,14 @@ describe("Global Trade System - Mystery Encounter", () => { // Set 2 Soul Dew on party lead scene.modifiers = []; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; - const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; + const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier; modifier.stackCount = 2; scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -247,7 +247,7 @@ describe("Global Trade System - Mystery Encounter", () => { // Set 1 Soul Dew on party lead scene.modifiers = []; const soulDew = generateModifierType(modifierTypes.SOUL_DEW)!; - const modifier = soulDew.newModifier(scene.getPlayerParty()[0]) as PokemonNatureWeightModifier; + const modifier = soulDew.newModifier(game.field.getPlayerPokemon()) as PokemonNatureWeightModifier; modifier.stackCount = 1; scene.addModifier(modifier, true, false, false, true); await scene.updateModifiers(true); diff --git a/test/mystery-encounter/encounters/lost-at-sea-encounter.test.ts b/test/mystery-encounter/encounters/lost-at-sea-encounter.test.ts index d29f8fe6a82..73134381553 100644 --- a/test/mystery-encounter/encounters/lost-at-sea-encounter.test.ts +++ b/test/mystery-encounter/encounters/lost-at-sea-encounter.test.ts @@ -99,9 +99,9 @@ describe("Lost at Sea - Mystery Encounter", () => { expect(option1.dialogue).toBeDefined(); expect(option1.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.1.label`, - disabledButtonLabel: `${namespace}:option.1.label_disabled`, + disabledButtonLabel: `${namespace}:option.1.labelDisabled`, buttonTooltip: `${namespace}:option.1.tooltip`, - disabledButtonTooltip: `${namespace}:option.1.tooltip_disabled`, + disabledButtonTooltip: `${namespace}:option.1.tooltipDisabled`, selected: [ { text: `${namespace}:option.1.selected`, @@ -162,9 +162,9 @@ describe("Lost at Sea - Mystery Encounter", () => { expect(option2.dialogue).toBeDefined(); expect(option2.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.2.label`, - disabledButtonLabel: `${namespace}:option.2.label_disabled`, + disabledButtonLabel: `${namespace}:option.2.labelDisabled`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.tooltip_disabled`, + disabledButtonTooltip: `${namespace}:option.2.tooltipDisabled`, selected: [ { text: `${namespace}:option.2.selected`, diff --git a/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts b/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts index 5412f269122..0c4e3044bbd 100644 --- a/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts +++ b/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts @@ -161,9 +161,9 @@ describe("Mysterious Challengers - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty); await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -205,9 +205,9 @@ describe("Mysterious Challengers - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty); await runMysteryEncounterToEnd(game, 2, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -262,9 +262,9 @@ describe("Mysterious Challengers - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty); await runMysteryEncounterToEnd(game, 3, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/mystery-encounter/encounters/part-timer-encounter.test.ts b/test/mystery-encounter/encounters/part-timer-encounter.test.ts index 63eea8bbca2..36a92b2b6bf 100644 --- a/test/mystery-encounter/encounters/part-timer-encounter.test.ts +++ b/test/mystery-encounter/encounters/part-timer-encounter.test.ts @@ -5,7 +5,6 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { SpeciesId } from "#enums/species-id"; -import { PokemonMove } from "#moves/pokemon-move"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { CIVILIZATION_ENCOUNTER_BIOMES } from "#mystery-encounters/mystery-encounters"; @@ -65,7 +64,7 @@ describe("Part-Timer - Mystery Encounter", () => { { text: `${namespace}:intro` }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]); expect(PartTimerEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); @@ -110,7 +109,7 @@ describe("Part-Timer - Mystery Encounter", () => { expect(EncounterPhaseUtils.updatePlayerMoney).toHaveBeenCalledWith(scene.getWaveMoneyAmount(1), true, false); // Expect PP of mon's moves to have been reduced to 2 - const moves = scene.getPlayerParty()[0].moveset; + const moves = game.field.getPlayerPokemon().moveset; for (const move of moves) { expect((move?.getMovePp() ?? 0) - (move?.ppUsed ?? 0)).toBe(2); } @@ -219,7 +218,7 @@ describe("Part-Timer - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, selected: [ { text: `${namespace}:option.3.selected`, @@ -233,7 +232,9 @@ describe("Part-Timer - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.PART_TIMER, defaultParty); // Mock movesets - scene.getPlayerParty().forEach(p => (p.moveset = [])); + scene.getPlayerParty().forEach(p => { + p.moveset = []; + }); await game.phaseInterceptor.to(MysteryEncounterPhase, false); const encounterPhase = scene.phaseManager.getCurrentPhase(); @@ -257,14 +258,14 @@ describe("Part-Timer - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.PART_TIMER, defaultParty); // Mock moveset - scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.ATTRACT)]; + game.move.changeMoveset(game.field.getPlayerPokemon(), MoveId.ATTRACT); await runMysteryEncounterToEnd(game, 3); expect(EncounterPhaseUtils.updatePlayerMoney).toHaveBeenCalledWith(scene.getWaveMoneyAmount(2.5), true, false); // Expect PP of mon's moves to have been reduced to 2 - const moves = scene.getPlayerParty()[0].moveset; + const moves = game.field.getPlayerPokemon().moveset; for (const move of moves) { - expect((move?.getMovePp() ?? 0) - (move?.ppUsed ?? 0)).toBe(2); + expect(move.getMovePp() - move.ppUsed).toBe(2); } }); diff --git a/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts b/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts index ff4f73cfbde..4d006abc636 100644 --- a/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts +++ b/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts @@ -146,7 +146,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { it("should NOT be selectable if the player doesn't have enough money", async () => { game.scene.money = 0; await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty); - await game.phaseInterceptor.to(MysteryEncounterPhase, false); + await game.phaseInterceptor.to("MysteryEncounterPhase", false); const encounterPhase = scene.phaseManager.getCurrentPhase(); expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name); @@ -207,7 +207,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.2.disabledTooltip`, selected: [ { text: `${namespace}:option.2.selected`, @@ -218,7 +218,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, [SpeciesId.BLASTOISE]); - await game.phaseInterceptor.to(MysteryEncounterPhase, false); + await game.phaseInterceptor.to("MysteryEncounterPhase", false); const encounterPhase = scene.phaseManager.getCurrentPhase(); expect(encounterPhase?.constructor.name).toBe(MysteryEncounterPhase.name); @@ -299,9 +299,9 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty); await runMysteryEncounterToEnd(game, 3, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts b/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts index 4556f7a7f45..ade98bfa99f 100644 --- a/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts +++ b/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts @@ -13,7 +13,6 @@ import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { HUMAN_TRANSITABLE_BIOMES } from "#mystery-encounters/mystery-encounters"; import { TheExpertPokemonBreederEncounter } from "#mystery-encounters/the-expert-pokemon-breeder-encounter"; import { CommandPhase } from "#phases/command-phase"; -import { PostMysteryEncounterPhase } from "#phases/mystery-encounter-phases"; import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, @@ -70,8 +69,8 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { text: `${namespace}:intro`, }, { - speaker: "trainerNames:expert_pokemon_breeder", - text: `${namespace}:intro_dialogue`, + speaker: "trainerNames:expertPokemonBreeder", + text: `${namespace}:introDialogue`, }, ]); expect(TheExpertPokemonBreederEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); @@ -123,7 +122,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { buttonTooltip: expect.any(String), // Varies based on pokemon selected: [ { - speaker: "trainerNames:expert_pokemon_breeder", + speaker: "trainerNames:expertPokemonBreeder", text: `${namespace}:option.selected`, }, ], @@ -176,7 +175,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); const eggsAfter = scene.gameData.eggs; @@ -187,8 +186,8 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { expect(eggsAfter.filter(egg => egg.tier === EggTier.COMMON).length).toBe(commonEggs); expect(eggsAfter.filter(egg => egg.tier === EggTier.RARE).length).toBe(rareEggs); - game.phaseInterceptor.superEndPhase(); - await game.phaseInterceptor.to(PostMysteryEncounterPhase); + game.endPhase(); + await game.phaseInterceptor.to("PostMysteryEncounterPhase"); const friendshipAfter = scene.currentBattle.mysteryEncounter!.misc.pokemon1.friendship; // 20 from ME + extra from winning battle (that extra is not accurate to what happens in game. @@ -208,7 +207,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { buttonTooltip: expect.any(String), // Varies based on pokemon selected: [ { - speaker: "trainerNames:expert_pokemon_breeder", + speaker: "trainerNames:expertPokemonBreeder", text: `${namespace}:option.selected`, }, ], @@ -261,7 +260,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); const eggsAfter = scene.gameData.eggs; @@ -272,8 +271,8 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { expect(eggsAfter.filter(egg => egg.tier === EggTier.COMMON).length).toBe(commonEggs); expect(eggsAfter.filter(egg => egg.tier === EggTier.RARE).length).toBe(rareEggs); - game.phaseInterceptor.superEndPhase(); - await game.phaseInterceptor.to(PostMysteryEncounterPhase); + game.endPhase(); + await game.phaseInterceptor.to("PostMysteryEncounterPhase"); const friendshipAfter = scene.currentBattle.mysteryEncounter!.misc.pokemon2.friendship; expect(friendshipAfter).toBe(friendshipBefore + 20 + FRIENDSHIP_GAIN_FROM_BATTLE); // 20 from ME + extra for friendship gained from winning battle @@ -290,7 +289,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { buttonTooltip: expect.any(String), // Varies based on pokemon selected: [ { - speaker: "trainerNames:expert_pokemon_breeder", + speaker: "trainerNames:expertPokemonBreeder", text: `${namespace}:option.selected`, }, ], @@ -343,7 +342,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 3, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); const eggsAfter = scene.gameData.eggs; @@ -354,8 +353,8 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { expect(eggsAfter.filter(egg => egg.tier === EggTier.COMMON).length).toBe(commonEggs); expect(eggsAfter.filter(egg => egg.tier === EggTier.RARE).length).toBe(rareEggs); - game.phaseInterceptor.superEndPhase(); - await game.phaseInterceptor.to(PostMysteryEncounterPhase); + game.endPhase(); + await game.phaseInterceptor.to("PostMysteryEncounterPhase"); const friendshipAfter = scene.currentBattle.mysteryEncounter!.misc.pokemon3.friendship; expect(friendshipAfter).toBe(friendshipBefore + 20 + FRIENDSHIP_GAIN_FROM_BATTLE); // 20 + extra for friendship gained from winning battle diff --git a/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts b/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts index 611a103dab2..3880c07c312 100644 --- a/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts +++ b/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts @@ -67,11 +67,11 @@ describe("The Pokemon Salesman - Mystery Encounter", () => { expect(dialogue).toBeDefined(); expect(dialogue.intro).toStrictEqual([ { text: `${namespace}:intro` }, - { speaker: `${namespace}:speaker`, text: `${namespace}:intro_dialogue` }, + { speaker: `${namespace}:speaker`, text: `${namespace}:introDialogue` }, ]); const { title, description, query } = dialogue.encounterOptionsDialogue!; expect(title).toBe(`${namespace}:title`); - expect(description).toMatch(new RegExp(`^${namespace}\\:description(_shiny)?$`)); + expect(description).toMatch(new RegExp(`^${namespace}\\:description(Shiny)?$`)); expect(query).toBe(`${namespace}:query`); expect(options.length).toBe(2); }); @@ -117,10 +117,10 @@ describe("The Pokemon Salesman - Mystery Encounter", () => { expect(dialogue).toBeDefined(); expect(dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.1.label`, - buttonTooltip: expect.stringMatching(new RegExp(`^${namespace}\\:option\\.1\\.tooltip(_shiny)?$`)), + buttonTooltip: expect.stringMatching(new RegExp(`^${namespace}\\:option\\.1\\.tooltip(Shiny)?$`)), selected: [ { - text: `${namespace}:option.1.selected_message`, + text: `${namespace}:option.1.selectedMessage`, }, ], }); diff --git a/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts b/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts index a314a14485f..3592e2dc774 100644 --- a/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts +++ b/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts @@ -229,9 +229,9 @@ describe("The Strong Stuff - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.THE_STRONG_STUFF, defaultParty); await runMysteryEncounterToEnd(game, 2, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/mystery-encounter/encounters/the-winstrate-challenge-encounter.test.ts b/test/mystery-encounter/encounters/the-winstrate-challenge-encounter.test.ts index ae2f9fd79ff..cf0ff7a94bd 100644 --- a/test/mystery-encounter/encounters/the-winstrate-challenge-encounter.test.ts +++ b/test/mystery-encounter/encounters/the-winstrate-challenge-encounter.test.ts @@ -16,7 +16,6 @@ import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { HUMAN_TRANSITABLE_BIOMES } from "#mystery-encounters/mystery-encounters"; import { TheWinstrateChallengeEncounter } from "#mystery-encounters/the-winstrate-challenge-encounter"; import { CommandPhase } from "#phases/command-phase"; -import { MysteryEncounterRewardsPhase } from "#phases/mystery-encounter-phases"; import { PartyHealPhase } from "#phases/party-heal-phase"; import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { VictoryPhase } from "#phases/victory-phase"; @@ -73,7 +72,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { { text: `${namespace}:intro` }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]); expect(TheWinstrateChallengeEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); @@ -295,9 +294,9 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { // Should have Macho Brace in the rewards await skipBattleToNextBattle(game, true); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -339,7 +338,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.THE_WINSTRATE_CHALLENGE, defaultParty); await runMysteryEncounterToEnd(game, 2); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -366,11 +365,10 @@ async function skipBattleToNextBattle(game: GameManager, isFinalBattle = false) p.status = new Status(StatusEffect.FAINT); game.scene.field.remove(p); }); - game.phaseInterceptor["onHold"] = []; game.scene.phaseManager.pushPhase(new VictoryPhase(0)); - game.phaseInterceptor.superEndPhase(); + game.endPhase(); if (isFinalBattle) { - await game.phaseInterceptor.to(MysteryEncounterRewardsPhase); + await game.phaseInterceptor.to("MysteryEncounterRewardsPhase"); } else { await game.toNextTurn(); } diff --git a/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts b/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts index 133fbfb10ba..7cc9a69b32d 100644 --- a/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts +++ b/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts @@ -169,15 +169,15 @@ describe("Trash to Treasure - Mystery Encounter", () => { }); }); - it("should give 2 Leftovers, 1 Shell Bell, and Black Sludge", async () => { + it("should give 1 Leftovers, 1 Shell Bell, and Black Sludge", async () => { await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty); await runMysteryEncounterToEnd(game, 1); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); const leftovers = scene.findModifier(m => m instanceof TurnHealModifier) as TurnHealModifier; expect(leftovers).toBeDefined(); - expect(leftovers?.stackCount).toBe(2); + expect(leftovers?.stackCount).toBe(1); const shellBell = scene.findModifier(m => m instanceof HitHealModifier) as HitHealModifier; expect(shellBell).toBeDefined(); @@ -242,9 +242,9 @@ describe("Trash to Treasure - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty); await runMysteryEncounterToEnd(game, 2, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts b/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts index 24d7960049e..5aadaf5c29a 100644 --- a/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts +++ b/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts @@ -11,7 +11,6 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { SpeciesId } from "#enums/species-id"; import { Stat } from "#enums/stat"; import type { BerryModifier } from "#modifiers/modifier"; -import { PokemonMove } from "#moves/pokemon-move"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import { generateModifierType } from "#mystery-encounters/encounter-phase-utils"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; @@ -172,7 +171,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.2.label`, buttonTooltip: `${namespace}:option.2.tooltip`, - disabledButtonTooltip: `${namespace}:option.2.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.2.disabledTooltip`, selected: [ { text: `${namespace}:option.2.selected`, @@ -214,11 +213,11 @@ describe("Uncommon Breed - Mystery Encounter", () => { // Berries on party lead const sitrus = generateModifierType(modifierTypes.BERRY, [BerryType.SITRUS])!; - const sitrusMod = sitrus.newModifier(scene.getPlayerParty()[0]) as BerryModifier; + const sitrusMod = sitrus.newModifier(game.field.getPlayerPokemon()) as BerryModifier; sitrusMod.stackCount = 2; scene.addModifier(sitrusMod, true, false, false, true); const ganlon = generateModifierType(modifierTypes.BERRY, [BerryType.GANLON])!; - const ganlonMod = ganlon.newModifier(scene.getPlayerParty()[0]) as BerryModifier; + const ganlonMod = ganlon.newModifier(game.field.getPlayerPokemon()) as BerryModifier; ganlonMod.stackCount = 3; scene.addModifier(ganlonMod, true, false, false, true); await scene.updateModifiers(true); @@ -237,7 +236,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { expect(option.dialogue).toStrictEqual({ buttonLabel: `${namespace}:option.3.label`, buttonTooltip: `${namespace}:option.3.tooltip`, - disabledButtonTooltip: `${namespace}:option.3.disabled_tooltip`, + disabledButtonTooltip: `${namespace}:option.3.disabledTooltip`, selected: [ { text: `${namespace}:option.3.selected`, @@ -270,7 +269,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); await game.runToMysteryEncounter(MysteryEncounterType.UNCOMMON_BREED, defaultParty); // Mock moveset - scene.getPlayerParty()[0].moveset = [new PokemonMove(MoveId.CHARM)]; + game.move.changeMoveset(game.field.getPlayerPokemon(), MoveId.CHARM); await runMysteryEncounterToEnd(game, 3); expect(leaveEncounterWithoutBattleSpy).toBeCalled(); diff --git a/test/mystery-encounter/encounters/weird-dream-encounter.test.ts b/test/mystery-encounter/encounters/weird-dream-encounter.test.ts index 9b430ec046e..e2ec7ae514a 100644 --- a/test/mystery-encounter/encounters/weird-dream-encounter.test.ts +++ b/test/mystery-encounter/encounters/weird-dream-encounter.test.ts @@ -68,7 +68,7 @@ describe("Weird Dream - Mystery Encounter", () => { }, { speaker: `${namespace}:speaker`, - text: `${namespace}:intro_dialogue`, + text: `${namespace}:introDialogue`, }, ]); expect(WeirdDreamEncounter.dialogue.encounterOptionsDialogue?.title).toBe(`${namespace}:title`); @@ -116,7 +116,7 @@ describe("Weird Dream - Mystery Encounter", () => { const bstsPrior = pokemonPrior.map(species => species.getSpeciesForm().getBaseStatTotal()); await runMysteryEncounterToEnd(game, 1); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); const pokemonAfter = scene.getPlayerParty(); @@ -139,9 +139,9 @@ describe("Weird Dream - Mystery Encounter", () => { it("should have 1 Memory Mushroom, 5 Rogue Balls, and 3 Mints in rewards", async () => { await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty); await runMysteryEncounterToEnd(game, 1); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -196,9 +196,9 @@ describe("Weird Dream - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty); await runMysteryEncounterToEnd(game, 2, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to(SelectModifierPhase, false); + await game.phaseInterceptor.to("SelectModifierPhase", false); expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/mystery-encounter/mystery-encounter-utils.test.ts b/test/mystery-encounter/mystery-encounter-utils.test.ts index adcc3111319..361c3f7480e 100644 --- a/test/mystery-encounter/mystery-encounter-utils.test.ts +++ b/test/mystery-encounter/mystery-encounter-utils.test.ts @@ -63,7 +63,7 @@ describe("Mystery Encounter Utils", () => { // Both pokemon fainted scene.getPlayerParty().forEach(p => { p.hp = 0; - p.trySetStatus(StatusEffect.FAINT); + p.doSetStatus(StatusEffect.FAINT); void p.updateInfo(); }); @@ -83,7 +83,7 @@ describe("Mystery Encounter Utils", () => { // Only faint 1st pokemon const party = scene.getPlayerParty(); party[0].hp = 0; - party[0].trySetStatus(StatusEffect.FAINT); + party[0].doSetStatus(StatusEffect.FAINT); await party[0].updateInfo(); // Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal) @@ -102,7 +102,7 @@ describe("Mystery Encounter Utils", () => { // Only faint 1st pokemon const party = scene.getPlayerParty(); party[0].hp = 0; - party[0].trySetStatus(StatusEffect.FAINT); + party[0].doSetStatus(StatusEffect.FAINT); await party[0].updateInfo(); // Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal) @@ -121,7 +121,7 @@ describe("Mystery Encounter Utils", () => { // Only faint 1st pokemon const party = scene.getPlayerParty(); party[0].hp = 0; - party[0].trySetStatus(StatusEffect.FAINT); + party[0].doSetStatus(StatusEffect.FAINT); await party[0].updateInfo(); // Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal) @@ -167,7 +167,7 @@ describe("Mystery Encounter Utils", () => { const party = scene.getPlayerParty(); party[0].level = 100; party[0].hp = 0; - party[0].trySetStatus(StatusEffect.FAINT); + party[0].doSetStatus(StatusEffect.FAINT); await party[0].updateInfo(); party[1].level = 10; @@ -206,7 +206,7 @@ describe("Mystery Encounter Utils", () => { const party = scene.getPlayerParty(); party[0].level = 10; party[0].hp = 0; - party[0].trySetStatus(StatusEffect.FAINT); + party[0].doSetStatus(StatusEffect.FAINT); await party[0].updateInfo(); party[1].level = 100; diff --git a/test/phases/form-change-phase.test.ts b/test/phases/form-change-phase.test.ts index 3caf824b252..17fe7f4449c 100644 --- a/test/phases/form-change-phase.test.ts +++ b/test/phases/form-change-phase.test.ts @@ -38,7 +38,7 @@ describe("Form Change Phase", () => { await game.classicMode.startBattle([SpeciesId.ZACIAN]); // Before the form change: Should be Hero form - const zacian = game.scene.getPlayerParty()[0]; + const zacian = game.field.getPlayerPokemon(); expect(zacian.getFormKey()).toBe("hero-of-many-battles"); expect(zacian.getTypes()).toStrictEqual([PokemonType.FAIRY]); expect(zacian.calculateBaseStats()).toStrictEqual([92, 120, 115, 80, 115, 138]); diff --git a/test/phases/mystery-encounter-phase.test.ts b/test/phases/mystery-encounter-phase.test.ts index 2b6105c7034..a3dc779b02c 100644 --- a/test/phases/mystery-encounter-phase.test.ts +++ b/test/phases/mystery-encounter-phase.test.ts @@ -37,7 +37,7 @@ describe("Mystery Encounter Phases", () => { SpeciesId.VOLCARONA, ]); - await game.phaseInterceptor.to(MysteryEncounterPhase, false); + await game.phaseInterceptor.to("MysteryEncounterPhase", false); expect(game.scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); }); @@ -49,9 +49,9 @@ describe("Mystery Encounter Phases", () => { game.onNextPrompt("MysteryEncounterPhase", UiMode.MYSTERY_ENCOUNTER, () => { // End phase early for test - game.phaseInterceptor.superEndPhase(); + game.endPhase(); }); - await game.phaseInterceptor.run(MysteryEncounterPhase); + await game.phaseInterceptor.to("MysteryEncounterPhase"); expect(game.scene.mysteryEncounterSaveData.encounteredEvents.length).toBeGreaterThan(0); expect(game.scene.mysteryEncounterSaveData.encounteredEvents[0].type).toEqual( @@ -75,7 +75,7 @@ describe("Mystery Encounter Phases", () => { handler.processInput(Button.ACTION); }); - await game.phaseInterceptor.run(MysteryEncounterPhase); + await game.phaseInterceptor.to("MysteryEncounterPhase"); // Select option 1 for encounter const handler = game.scene.ui.getHandler() as MysteryEncounterUiHandler; diff --git a/test/phases/select-modifier-phase.test.ts b/test/phases/select-modifier-phase.test.ts index ae4cebb1866..b77e31e931f 100644 --- a/test/phases/select-modifier-phase.test.ts +++ b/test/phases/select-modifier-phase.test.ts @@ -241,7 +241,7 @@ describe("SelectModifierPhase", () => { const selectModifierPhase = new SelectModifierPhase(0, undefined, customModifiers); scene.phaseManager.unshiftPhase(selectModifierPhase); game.move.select(MoveId.SPLASH); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -265,7 +265,7 @@ describe("SelectModifierPhase", () => { const selectModifierPhase = new SelectModifierPhase(0, undefined, customModifiers); scene.phaseManager.unshiftPhase(selectModifierPhase); game.move.select(MoveId.SPLASH); - await game.phaseInterceptor.run(SelectModifierPhase); + await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( diff --git a/test/test-utils/game-manager.ts b/test/test-utils/game-manager.ts index 05b3be21d26..57badd866b1 100644 --- a/test/test-utils/game-manager.ts +++ b/test/test-utils/game-manager.ts @@ -20,13 +20,11 @@ import { ModifierTypeOption } from "#modifiers/modifier-type"; import { CheckSwitchPhase } from "#phases/check-switch-phase"; import { CommandPhase } from "#phases/command-phase"; import { EncounterPhase } from "#phases/encounter-phase"; -import { LoginPhase } from "#phases/login-phase"; import { MovePhase } from "#phases/move-phase"; import { MysteryEncounterPhase } from "#phases/mystery-encounter-phases"; import { NewBattlePhase } from "#phases/new-battle-phase"; import { SelectStarterPhase } from "#phases/select-starter-phase"; import type { SelectTargetPhase } from "#phases/select-target-phase"; -import { TitlePhase } from "#phases/title-phase"; import { TurnEndPhase } from "#phases/turn-end-phase"; import { TurnInitPhase } from "#phases/turn-init-phase"; import { TurnStartPhase } from "#phases/turn-start-phase"; @@ -188,10 +186,12 @@ export class GameManager { * @returns A promise that resolves when the title phase is reached. */ async runToTitle(): Promise { - await this.phaseInterceptor.whenAboutToRun(LoginPhase); - this.phaseInterceptor.pop(); - await this.phaseInterceptor.run(TitlePhase); + // Go to login phase and skip past it + await this.phaseInterceptor.to("LoginPhase", false); + this.phaseInterceptor.shiftPhase(true); + await this.phaseInterceptor.to("TitlePhase"); + // TODO: This should be moved to a separate initialization method this.scene.gameSpeed = 5; this.scene.moveAnimations = false; this.scene.showLevelUpStats = false; @@ -270,7 +270,7 @@ export class GameManager { true, ); - await this.phaseInterceptor.run(EncounterPhase); + await this.phaseInterceptor.to("EncounterPhase"); if (!isNullOrUndefined(encounterType)) { expect(this.scene.currentBattle?.mysteryEncounter?.encounterType).toBe(encounterType); } @@ -542,7 +542,7 @@ export class GameManager { * ``` */ async setTurnOrder(order: BattlerIndex[]): Promise { - await this.phaseInterceptor.to(TurnStartPhase, false); + await this.phaseInterceptor.to("TurnStartPhase", false); vi.spyOn(this.scene.phaseManager.getCurrentPhase() as TurnStartPhase, "getSpeedOrder").mockReturnValue(order); } diff --git a/test/test-utils/helpers/challenge-mode-helper.ts b/test/test-utils/helpers/challenge-mode-helper.ts index a8a9ff89de6..a6d4b5c3b5a 100644 --- a/test/test-utils/helpers/challenge-mode-helper.ts +++ b/test/test-utils/helpers/challenge-mode-helper.ts @@ -49,7 +49,7 @@ export class ChallengeModeHelper extends GameManagerHelper { selectStarterPhase.initBattle(starters); }); - await this.game.phaseInterceptor.run(EncounterPhase); + await this.game.phaseInterceptor.to("EncounterPhase"); if (overrides.ENEMY_HELD_ITEMS_OVERRIDE.length === 0 && this.game.override.removeEnemyStartingItems) { this.game.removeEnemyHeldItems(); } diff --git a/test/test-utils/helpers/field-helper.ts b/test/test-utils/helpers/field-helper.ts index 2d8fd8ee701..29eb70ae20c 100644 --- a/test/test-utils/helpers/field-helper.ts +++ b/test/test-utils/helpers/field-helper.ts @@ -5,6 +5,7 @@ import type { globalScene } from "#app/global-scene"; import type { Ability } from "#abilities/ability"; import { allAbilities } from "#data/data-lists"; import type { AbilityId } from "#enums/ability-id"; +import type { BattlerIndex } from "#enums/battler-index"; import type { PokemonType } from "#enums/pokemon-type"; import { Stat } from "#enums/stat"; import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon"; @@ -45,20 +46,38 @@ export class FieldHelper extends GameManagerHelper { /** * Helper function to return all on-field {@linkcode Pokemon} in speed order (fastest first). - * @returns An array containing all {@linkcode Pokemon} on the field in order of descending Speed. + * @param indices - Whether to only return {@linkcode BattlerIndex}es instead of full Pokemon objects + * (such as for comparison with other speed order-related mechanisms); default `false` + * @returns An array containing all on-field {@linkcode Pokemon} in order of descending Speed. \ * Speed ties are returned in increasing order of index. * * @remarks * This does not account for Trick Room as it does not modify the _speed_ of Pokemon on the field, * only their turn order. */ - public getSpeedOrder(): Pokemon[] { - return this.game.scene + public getSpeedOrder(indices?: false): Pokemon[]; + + /** + * Helper function to return all on-field {@linkcode Pokemon} in speed order (fastest first). + * @param indices - Whether to only return {@linkcode BattlerIndex}es instead of full Pokemon objects + * (such as for comparison with other speed order-related mechanisms); default `false` + * @returns An array containing the {@linkcode BattlerIndex}es of all on-field {@linkcode Pokemon} on the field in order of descending Speed. \ + * Speed ties are returned in increasing order of index. + * + * @remarks + * This does not account for Trick Room as it does not modify the _speed_ of Pokemon on the field, + * only their turn order. + */ + public getSpeedOrder(indices: true): BattlerIndex[]; + public getSpeedOrder(indices = false): BattlerIndex[] | Pokemon[] { + const ret = this.game.scene .getField(true) .sort( (pA, pB) => pB.getEffectiveStat(Stat.SPD) - pA.getEffectiveStat(Stat.SPD) || pA.getBattlerIndex() - pB.getBattlerIndex(), ); + + return indices ? ret.map(p => p.getBattlerIndex()) : ret; } /** diff --git a/test/test-utils/helpers/reload-helper.ts b/test/test-utils/helpers/reload-helper.ts index a8ed0e21307..7166f1b6cf9 100644 --- a/test/test-utils/helpers/reload-helper.ts +++ b/test/test-utils/helpers/reload-helper.ts @@ -57,7 +57,7 @@ export class ReloadHelper extends GameManagerHelper { this.game.scene.modifiers = []; } titlePhase.loadSaveSlot(-1); // Load the desired session data - this.game.phaseInterceptor.shift(); // Loading the save slot also ended TitlePhase, clean it up + this.game.phaseInterceptor.shiftPhase(); // Loading the save slot also ended TitlePhase, clean it up // Run through prompts for switching Pokemon, copied from classicModeHelper.ts if (this.game.scene.battleStyle === BattleStyle.SWITCH) { diff --git a/test/test-utils/matchers/to-have-arena-tag.ts b/test/test-utils/matchers/to-have-arena-tag.ts index dee7c133f25..e2a4a71ffd5 100644 --- a/test/test-utils/matchers/to-have-arena-tag.ts +++ b/test/test-utils/matchers/to-have-arena-tag.ts @@ -1,5 +1,5 @@ import type { ArenaTag, ArenaTagTypeMap } from "#data/arena-tag"; -import type { ArenaTagSide } from "#enums/arena-tag-side"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import type { ArenaTagType } from "#enums/arena-tag-type"; import type { OneOther } from "#test/@types/test-helpers"; // biome-ignore lint/correctness/noUnusedImports: TSDoc @@ -26,7 +26,7 @@ export function toHaveArenaTag( this: MatcherState, received: unknown, expectedTag: T | toHaveArenaTagOptions, - side?: ArenaTagSide, + side: ArenaTagSide = ArenaTagSide.BOTH, ): SyncExpectationResult { if (!isGameManagerInstance(received)) { return { @@ -46,22 +46,27 @@ export function toHaveArenaTag( // Bangs are ok as we enforce safety via overloads // @ts-expect-error - Typescript is being stupid as tag type and side will always exist const etag: Partial & { tagType: T; side: ArenaTagSide } = - typeof expectedTag === "object" ? expectedTag : { tagType: expectedTag, side: side! }; + typeof expectedTag === "object" ? expectedTag : { tagType: expectedTag, side }; + // If checking only tag type/side OR no tags were found, break out early. // We need to get all tags for the case of checking properties of a tag present on both sides of the arena const tags = received.scene.arena.findTagsOnSide(t => t.tagType === etag.tagType, etag.side); - if (tags.length === 0) { + if (typeof expectedTag !== "object" || tags.length === 0) { + const pass = tags.length > 0; return { - pass: false, - message: () => `Expected the Arena to have a tag of type ${etag.tagType}, but it didn't!`, - expected: etag.tagType, - actual: received.scene.arena.tags.map(t => t.tagType), + pass, + message: () => + pass + ? `Expected the Arena to NOT have a tag of type ${etag.tagType}, but it did!` + : `Expected the Arena to have a tag of type ${etag.tagType}, but it didn't!`, + expected: etag, + actual: received.scene.arena.tags.map(t => ({ tagType: t.tagType, side: t.side })), }; } // Pass if any of the matching tags meet our criteria const pass = tags.some(tag => - this.equals(tag, expectedTag, [...this.customTesters, this.utils.subsetEquality, this.utils.iterableEquality]), + this.equals(tag, etag, [...this.customTesters, this.utils.subsetEquality, this.utils.iterableEquality]), ); const expectedStr = getOnelineDiffStr.call(this, expectedTag); diff --git a/test/test-utils/phase-interceptor.ts b/test/test-utils/phase-interceptor.ts index 50de7e9f047..0d357a75557 100644 --- a/test/test-utils/phase-interceptor.ts +++ b/test/test-utils/phase-interceptor.ts @@ -1,3 +1,4 @@ +import type { BattleScene } from "#app/battle-scene"; import { Phase } from "#app/phase"; import { UiMode } from "#enums/ui-mode"; import { AttemptRunPhase } from "#phases/attempt-run-phase"; @@ -64,6 +65,7 @@ import { UnlockPhase } from "#phases/unlock-phase"; import { VictoryPhase } from "#phases/victory-phase"; import { ErrorInterceptor } from "#test/test-utils/error-interceptor"; import type { PhaseClass, PhaseString } from "#types/phase-types"; +import type { AwaitableUiHandler } from "#ui/awaitable-ui-handler"; import { UI } from "#ui/ui"; export interface PromptHandler { @@ -76,20 +78,39 @@ export interface PromptHandler { type PhaseInterceptorPhase = PhaseClass | PhaseString; +interface PhaseStub { + start(): void; + endBySetMode: boolean; +} + +interface InProgressStub { + name: string; + callback(): void; + onError(error: any): void; +} + +interface onHoldStub { + name: string; + call(): void; +} + export class PhaseInterceptor { - public scene; - public phases = {}; - public log: string[]; - private onHold; - private interval; - private promptInterval; - private intervalRun; + public scene: BattleScene; + // @ts-expect-error: initialized in `initPhases` + public phases: Record = {}; + public log: PhaseString[]; + /** + * TODO: This should not be an array; + * Our linear phase system means only 1 phase is ever started at once (if any) + */ + private onHold: onHoldStub[]; + private interval: NodeJS.Timeout; + private promptInterval: NodeJS.Timeout; + private intervalRun: NodeJS.Timeout; private prompts: PromptHandler[]; - private phaseFrom; - private inProgress; - private originalSetMode; - private originalSetOverlayMode; - private originalSuperEnd; + private inProgress?: InProgressStub; + private originalSetMode: UI["setMode"]; + private originalSuperEnd: Phase["end"]; /** * List of phases with their corresponding start methods. @@ -100,72 +121,73 @@ export class PhaseInterceptor { * `initPhases()` so that its subclasses can use `super.start()` properly. */ private PHASES = [ - [LoginPhase, this.startPhase], - [TitlePhase, this.startPhase], - [SelectGenderPhase, 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], - [DamageAnimPhase, 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], - [FormChangePhase, this.startPhase], - [EvolutionPhase, this.startPhase], - [EndEvolutionPhase, this.startPhase], - [LevelCapPhase, this.startPhase], - [AttemptRunPhase, this.startPhase], - [SelectBiomePhase, this.startPhase], - [PositionalTagPhase, this.startPhase], - [PokemonTransformPhase, this.startPhase], - [MysteryEncounterPhase, this.startPhase], - [MysteryEncounterOptionSelectedPhase, this.startPhase], - [MysteryEncounterBattlePhase, this.startPhase], - [MysteryEncounterRewardsPhase, this.startPhase], - [PostMysteryEncounterPhase, this.startPhase], - [RibbonModifierRewardPhase, this.startPhase], - [GameOverModifierRewardPhase, this.startPhase], - [ModifierRewardPhase, this.startPhase], - [PartyExpPhase, this.startPhase], - [ExpPhase, this.startPhase], - [EncounterPhase, this.startPhase], - [GameOverPhase, this.startPhase], - [UnlockPhase, this.startPhase], - [PostGameOverPhase, this.startPhase], - [RevivalBlessingPhase, this.startPhase], + LoginPhase, + TitlePhase, + SelectGenderPhase, + NewBiomeEncounterPhase, + SelectStarterPhase, + PostSummonPhase, + SummonPhase, + ToggleDoublePositionPhase, + CheckSwitchPhase, + ShowAbilityPhase, + MessagePhase, + TurnInitPhase, + CommandPhase, + EnemyCommandPhase, + TurnStartPhase, + MovePhase, + MoveEffectPhase, + DamageAnimPhase, + FaintPhase, + BerryPhase, + TurnEndPhase, + BattleEndPhase, + EggLapsePhase, + SelectModifierPhase, + NextEncounterPhase, + NewBattlePhase, + VictoryPhase, + LearnMovePhase, + MoveEndPhase, + StatStageChangePhase, + ShinySparklePhase, + SelectTargetPhase, + UnavailablePhase, + QuietFormChangePhase, + SwitchPhase, + SwitchSummonPhase, + PartyHealPhase, + FormChangePhase, + EvolutionPhase, + EndEvolutionPhase, + LevelCapPhase, + AttemptRunPhase, + SelectBiomePhase, + PositionalTagPhase, + PokemonTransformPhase, + MysteryEncounterPhase, + MysteryEncounterOptionSelectedPhase, + MysteryEncounterBattlePhase, + MysteryEncounterRewardsPhase, + PostMysteryEncounterPhase, + RibbonModifierRewardPhase, + GameOverModifierRewardPhase, + ModifierRewardPhase, + PartyExpPhase, + ExpPhase, + EncounterPhase, + GameOverPhase, + UnlockPhase, + PostGameOverPhase, + RevivalBlessingPhase, ]; private endBySetMode = [ TitlePhase, SelectGenderPhase, CommandPhase, + SelectStarterPhase, SelectModifierPhase, MysteryEncounterPhase, PostMysteryEncounterPhase, @@ -175,7 +197,7 @@ export class PhaseInterceptor { * Constructor to initialize the scene and properties, and to start the phase handling. * @param scene - The scene to be managed. */ - constructor(scene) { + constructor(scene: BattleScene) { this.scene = scene; this.onHold = []; this.prompts = []; @@ -200,16 +222,6 @@ export class PhaseInterceptor { } } - /** - * Method to set the starting phase. - * @param phaseFrom - The phase to start from. - * @returns The instance of the PhaseInterceptor. - */ - runFrom(phaseFrom: PhaseInterceptorPhase): PhaseInterceptor { - this.phaseFrom = phaseFrom; - return this; - } - /** * Method to transition to a target phase. * @param phaseTo - The phase to transition to. @@ -219,59 +231,50 @@ export class PhaseInterceptor { async to(phaseTo: PhaseInterceptorPhase, runTarget = true): Promise { return new Promise(async (resolve, reject) => { ErrorInterceptor.getInstance().add(this); - if (this.phaseFrom) { - await this.run(this.phaseFrom).catch(e => reject(e)); - this.phaseFrom = null; - } const targetName = typeof phaseTo === "string" ? phaseTo : phaseTo.name; this.intervalRun = setInterval(async () => { const currentPhase = this.onHold?.length && this.onHold[0]; - if (currentPhase && currentPhase.name === targetName) { - clearInterval(this.intervalRun); - if (!runTarget) { - return resolve(); - } - await this.run(currentPhase).catch(e => { + if (!currentPhase) { + // No current phase means the manager either hasn't started yet + // or we were interrupted by prompt; wait for phase to finish + return; + } + + // If current phase is different, run it and wait for it to finish. + if (currentPhase.name !== targetName) { + await this.run().catch(e => { clearInterval(this.intervalRun); return reject(e); }); + return; + } + + // Hit target phase; run it and resolve + clearInterval(this.intervalRun); + if (!runTarget) { return resolve(); } - if (currentPhase && currentPhase.name !== targetName) { - await this.run(currentPhase).catch(e => { - clearInterval(this.intervalRun); - return reject(e); - }); - } + await this.run().catch(e => { + clearInterval(this.intervalRun); + return reject(e); + }); + return resolve(); }); }); } /** - * Method to run a phase with an optional skip function. - * @param phaseTarget - The phase to run. - * @param skipFn - Optional skip function. + * Method to run the current phase with an optional skip function. * @returns A promise that resolves when the phase is run. */ - run(phaseTarget: PhaseInterceptorPhase, skipFn?: (className: PhaseClass) => boolean): Promise { - const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name; - this.scene.moveAnimations = null; // Mandatory to avoid crash + private run(): Promise { + // @ts-expect-error: This is apparently mandatory to avoid a crash; review if this is needed + this.scene.moveAnimations = null; return new Promise(async (resolve, reject) => { ErrorInterceptor.getInstance().add(this); const interval = setInterval(async () => { const currentPhase = this.onHold.shift(); if (currentPhase) { - if (currentPhase.name !== targetName) { - clearInterval(interval); - const skip = skipFn?.(currentPhase.name); - if (skip) { - this.onHold.unshift(currentPhase); - ErrorInterceptor.getInstance().remove(this); - return resolve(); - } - clearInterval(interval); - return reject(`Wrong phase: this is ${currentPhase.name} and not ${targetName}`); - } clearInterval(interval); this.inProgress = { name: currentPhase.name, @@ -287,26 +290,6 @@ export class PhaseInterceptor { }); } - 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) => { - ErrorInterceptor.getInstance().add(this); - const interval = setInterval(async () => { - const currentPhase = this.onHold[0]; - if (currentPhase?.name === targetName) { - clearInterval(interval); - resolve(); - } - }); - }); - } - - pop() { - this.onHold.pop(); - this.scene.phaseManager.shiftPhase(); - } - /** * Remove the current phase from the phase interceptor. * @@ -316,7 +299,7 @@ export class PhaseInterceptor { * * @param shouldRun Whether or not the current scene should also be run. */ - shift(shouldRun = false): void { + shiftPhase(shouldRun = false): void { this.onHold.shift(); if (shouldRun) { this.scene.phaseManager.shiftPhase(); @@ -328,17 +311,16 @@ export class PhaseInterceptor { */ initPhases() { this.originalSetMode = UI.prototype.setMode; - this.originalSetOverlayMode = UI.prototype.setOverlayMode; 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 of this.PHASES) { const originalStart = phase.prototype.start; this.phases[phase.name] = { start: originalStart, endBySetMode: this.endBySetMode.some(elm => elm.name === phase.name), }; - phase.prototype.start = () => methodStart.call(this, phase); + phase.prototype.start = () => this.startPhase.call(this, phase); } } @@ -347,7 +329,7 @@ export class PhaseInterceptor { * @param phase - The phase to start. */ startPhase(phase: PhaseClass) { - this.log.push(phase.name); + this.log.push(phase.name as PhaseString); const instance = this.scene.phaseManager.getCurrentPhase(); this.onHold.push({ name: phase.name, @@ -357,16 +339,11 @@ export class PhaseInterceptor { }); } - unlock() { - this.inProgress?.callback(); - this.inProgress = undefined; - } - /** * Method to end a phase and log it. * @param phase - The phase to start. */ - superEndPhase() { + private superEndPhase() { const instance = this.scene.phaseManager.getCurrentPhase(); this.originalSuperEnd.apply(instance); this.inProgress?.callback(); @@ -379,7 +356,8 @@ export class PhaseInterceptor { * @param args - Additional arguments to pass to the original method. */ setMode(mode: UiMode, ...args: unknown[]): Promise { - const currentPhase = this.scene.phaseManager.getCurrentPhase(); + // TODO: remove the `!` in PR 6243 / after PR 6243 is merged + const currentPhase = this.scene.phaseManager.getCurrentPhase()!; const instance = this.scene.ui; console.log("setMode", `${UiMode[mode]} (=${mode})`, args); const ret = this.originalSetMode.apply(instance, [mode, ...args]); @@ -395,18 +373,6 @@ export class PhaseInterceptor { return ret; } - /** - * mock to set overlay mode - * @param mode - The {@linkcode Mode} to set. - * @param args - Additional arguments to pass to the original method. - */ - setOverlayMode(mode: UiMode, ...args: unknown[]): Promise { - const instance = this.scene.ui; - console.log("setOverlayMode", `${UiMode[mode]} (=${mode})`, args); - const ret = this.originalSetOverlayMode.apply(instance, [mode, ...args]); - return ret; - } - /** * Method to start the prompt handler. */ @@ -425,7 +391,7 @@ export class PhaseInterceptor { currentPhase === actionForNextPrompt.phaseTarget && currentHandler.active && (!actionForNextPrompt.awaitingActionInput || - (actionForNextPrompt.awaitingActionInput && currentHandler.awaitingActionInput)) + (actionForNextPrompt.awaitingActionInput && (currentHandler as AwaitableUiHandler)["awaitingActionInput"])) ) { const prompt = this.prompts.shift(); if (prompt?.callback) { @@ -467,11 +433,10 @@ export 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; - UI.prototype.setOverlayMode = this.originalSetOverlayMode; Phase.prototype.end = this.originalSuperEnd; clearInterval(this.promptInterval); clearInterval(this.interval); diff --git a/test/ui/pokedex.test.ts b/test/ui/pokedex.test.ts index 217c1f09a3b..edd9fa879d0 100644 --- a/test/ui/pokedex.test.ts +++ b/test/ui/pokedex.test.ts @@ -69,7 +69,7 @@ describe("UI - Pokedex", () => { // Open the pokedex UI. await game.runToTitle(); - await game.phaseInterceptor.setOverlayMode(UiMode.POKEDEX); + await game.scene.ui.setOverlayMode(UiMode.POKEDEX); // Get the handler for the current UI. const handler = game.scene.ui.getHandler(); @@ -89,7 +89,7 @@ describe("UI - Pokedex", () => { // Open the pokedex UI. await game.runToTitle(); - await game.phaseInterceptor.setOverlayMode(UiMode.POKEDEX_PAGE, species, starterAttributes); + await game.scene.ui.setOverlayMode(UiMode.POKEDEX_PAGE, species, starterAttributes); // Get the handler for the current UI. const handler = game.scene.ui.getHandler(); diff --git a/test/ui/starter-select.test.ts b/test/ui/starter-select.test.ts index 6dc9603c8b3..397f3d6086f 100644 --- a/test/ui/starter-select.test.ts +++ b/test/ui/starter-select.test.ts @@ -6,8 +6,6 @@ import { GameModes } from "#enums/game-modes"; import { Nature } from "#enums/nature"; import { SpeciesId } from "#enums/species-id"; import { UiMode } from "#enums/ui-mode"; -import { EncounterPhase } from "#phases/encounter-phase"; -import { SelectStarterPhase } from "#phases/select-starter-phase"; import type { TitlePhase } from "#phases/title-phase"; import { GameManager } from "#test/test-utils/game-manager"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler"; @@ -54,9 +52,8 @@ describe("UI - Starter select", () => { handler.processInput(Button.RIGHT); handler.processInput(Button.LEFT); handler.processInput(Button.ACTION); - game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.run(SelectStarterPhase); + await game.phaseInterceptor.to("SelectStarterPhase"); let options: OptionSelectItem[] = []; let optionSelectUiHandler: OptionSelectUiHandler | undefined; await new Promise(resolve => { @@ -88,12 +85,12 @@ describe("UI - Starter select", () => { resolve(); }); }); - await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + await game.phaseInterceptor.to("EncounterPhase", false); - expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); - expect(game.scene.getPlayerParty()[0].shiny).toBe(true); - expect(game.scene.getPlayerParty()[0].variant).toBe(2); - expect(game.scene.getPlayerParty()[0].gender).toBe(Gender.MALE); + expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR); + expect(game.field.getPlayerPokemon().shiny).toBe(true); + expect(game.field.getPlayerPokemon().variant).toBe(2); + expect(game.field.getPlayerPokemon().gender).toBe(Gender.MALE); }); it("Bulbasaur - shiny - variant 2 female hardy overgrow", async () => { @@ -115,9 +112,8 @@ describe("UI - Starter select", () => { handler.processInput(Button.LEFT); handler.processInput(Button.CYCLE_GENDER); handler.processInput(Button.ACTION); - game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.run(SelectStarterPhase); + await game.phaseInterceptor.to("SelectStarterPhase"); let options: OptionSelectItem[] = []; let optionSelectUiHandler: OptionSelectUiHandler | undefined; await new Promise(resolve => { @@ -149,13 +145,13 @@ describe("UI - Starter select", () => { resolve(); }); }); - await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + await game.phaseInterceptor.to("EncounterPhase", false); - expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); - expect(game.scene.getPlayerParty()[0].shiny).toBe(true); - expect(game.scene.getPlayerParty()[0].variant).toBe(2); - expect(game.scene.getPlayerParty()[0].nature).toBe(Nature.HARDY); - expect(game.scene.getPlayerParty()[0].getAbility().id).toBe(AbilityId.OVERGROW); + expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR); + expect(game.field.getPlayerPokemon().shiny).toBe(true); + expect(game.field.getPlayerPokemon().variant).toBe(2); + expect(game.field.getPlayerPokemon().nature).toBe(Nature.HARDY); + expect(game.field.getPlayerPokemon().getAbility().id).toBe(AbilityId.OVERGROW); }); it("Bulbasaur - shiny - variant 2 female lonely chlorophyl", async () => { @@ -179,9 +175,8 @@ describe("UI - Starter select", () => { handler.processInput(Button.CYCLE_NATURE); handler.processInput(Button.CYCLE_ABILITY); handler.processInput(Button.ACTION); - game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.run(SelectStarterPhase); + await game.phaseInterceptor.to("SelectStarterPhase"); let options: OptionSelectItem[] = []; let optionSelectUiHandler: OptionSelectUiHandler | undefined; await new Promise(resolve => { @@ -213,14 +208,14 @@ describe("UI - Starter select", () => { resolve(); }); }); - await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + await game.phaseInterceptor.to("EncounterPhase", false); - expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); - expect(game.scene.getPlayerParty()[0].shiny).toBe(true); - expect(game.scene.getPlayerParty()[0].variant).toBe(2); - expect(game.scene.getPlayerParty()[0].gender).toBe(Gender.FEMALE); - expect(game.scene.getPlayerParty()[0].nature).toBe(Nature.LONELY); - expect(game.scene.getPlayerParty()[0].getAbility().id).toBe(AbilityId.CHLOROPHYLL); + expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR); + expect(game.field.getPlayerPokemon().shiny).toBe(true); + expect(game.field.getPlayerPokemon().variant).toBe(2); + expect(game.field.getPlayerPokemon().gender).toBe(Gender.FEMALE); + expect(game.field.getPlayerPokemon().nature).toBe(Nature.LONELY); + expect(game.field.getPlayerPokemon().getAbility().id).toBe(AbilityId.CHLOROPHYLL); }); it("Bulbasaur - shiny - variant 2 female", async () => { @@ -242,9 +237,8 @@ describe("UI - Starter select", () => { handler.processInput(Button.LEFT); handler.processInput(Button.CYCLE_GENDER); handler.processInput(Button.ACTION); - game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.run(SelectStarterPhase); + await game.phaseInterceptor.to("SelectStarterPhase"); let options: OptionSelectItem[] = []; let optionSelectUiHandler: OptionSelectUiHandler | undefined; await new Promise(resolve => { @@ -276,12 +270,12 @@ describe("UI - Starter select", () => { resolve(); }); }); - await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + await game.phaseInterceptor.to("EncounterPhase", false); - expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); - expect(game.scene.getPlayerParty()[0].shiny).toBe(true); - expect(game.scene.getPlayerParty()[0].variant).toBe(2); - expect(game.scene.getPlayerParty()[0].gender).toBe(Gender.FEMALE); + expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR); + expect(game.field.getPlayerPokemon().shiny).toBe(true); + expect(game.field.getPlayerPokemon().variant).toBe(2); + expect(game.field.getPlayerPokemon().gender).toBe(Gender.FEMALE); }); it("Bulbasaur - not shiny", async () => { @@ -303,9 +297,8 @@ describe("UI - Starter select", () => { handler.processInput(Button.LEFT); handler.processInput(Button.ACTION); handler.processInput(Button.CYCLE_SHINY); - game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.run(SelectStarterPhase); + await game.phaseInterceptor.to("SelectStarterPhase"); let options: OptionSelectItem[] = []; let optionSelectUiHandler: OptionSelectUiHandler | undefined; await new Promise(resolve => { @@ -337,11 +330,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + await game.phaseInterceptor.to("EncounterPhase", false); - expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); - expect(game.scene.getPlayerParty()[0].shiny).toBe(false); - expect(game.scene.getPlayerParty()[0].variant).toBe(0); + expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR); + expect(game.field.getPlayerPokemon().shiny).toBe(false); + expect(game.field.getPlayerPokemon().variant).toBe(0); }); it("Bulbasaur - shiny - variant 1", async () => { @@ -365,9 +358,8 @@ describe("UI - Starter select", () => { handler.processInput(Button.CYCLE_SHINY); handler.processInput(Button.CYCLE_SHINY); handler.processInput(Button.ACTION); - game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.run(SelectStarterPhase); + await game.phaseInterceptor.to("SelectStarterPhase"); let options: OptionSelectItem[] = []; let optionSelectUiHandler: OptionSelectUiHandler | undefined; await new Promise(resolve => { @@ -399,11 +391,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + await game.phaseInterceptor.to("EncounterPhase", false); - expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); - expect(game.scene.getPlayerParty()[0].shiny).toBe(true); - expect(game.scene.getPlayerParty()[0].variant).toBe(1); + expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR); + expect(game.field.getPlayerPokemon().shiny).toBe(true); + expect(game.field.getPlayerPokemon().variant).toBe(1); }); it("Bulbasaur - shiny - variant 0", async () => { @@ -426,9 +418,8 @@ describe("UI - Starter select", () => { handler.processInput(Button.CYCLE_SHINY); handler.processInput(Button.CYCLE_SHINY); handler.processInput(Button.ACTION); - game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.run(SelectStarterPhase); + await game.phaseInterceptor.to("SelectStarterPhase"); let options: OptionSelectItem[] = []; let optionSelectUiHandler: OptionSelectUiHandler | undefined; await new Promise(resolve => { @@ -460,11 +451,11 @@ describe("UI - Starter select", () => { resolve(); }); }); - await game.phaseInterceptor.whenAboutToRun(EncounterPhase); + await game.phaseInterceptor.to("EncounterPhase", false); - expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.BULBASAUR); - expect(game.scene.getPlayerParty()[0].shiny).toBe(true); - expect(game.scene.getPlayerParty()[0].variant).toBe(0); + expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.BULBASAUR); + expect(game.field.getPlayerPokemon().shiny).toBe(true); + expect(game.field.getPlayerPokemon().variant).toBe(0); }); it("Check if first pokemon in party is caterpie from gen 1 and 1rd row, 3rd column", async () => { @@ -486,9 +477,8 @@ describe("UI - Starter select", () => { handler.processInput(Button.RIGHT); handler.processInput(Button.RIGHT); handler.processInput(Button.ACTION); - game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.run(SelectStarterPhase); + await game.phaseInterceptor.to("SelectStarterPhase"); let options: OptionSelectItem[] = []; let optionSelectUiHandler: OptionSelectUiHandler | undefined; await new Promise(resolve => { @@ -527,8 +517,8 @@ describe("UI - Starter select", () => { const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; saveSlotSelectUiHandler.processInput(Button.ACTION); }); - await game.phaseInterceptor.whenAboutToRun(EncounterPhase); - expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.CATERPIE); + await game.phaseInterceptor.to("EncounterPhase", false); + expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.CATERPIE); }); it("Check if first pokemon in party is nidoran_m from gen 1 and 2nd row, 4th column (cursor (9+4)-1)", async () => { @@ -551,9 +541,8 @@ describe("UI - Starter select", () => { handler.processInput(Button.RIGHT); handler.processInput(Button.DOWN); handler.processInput(Button.ACTION); - game.phaseInterceptor.unlock(); }); - await game.phaseInterceptor.run(SelectStarterPhase); + await game.phaseInterceptor.to("SelectStarterPhase"); let options: OptionSelectItem[] = []; let optionSelectUiHandler: OptionSelectUiHandler | undefined; await new Promise(resolve => { @@ -593,7 +582,7 @@ describe("UI - Starter select", () => { const saveSlotSelectUiHandler = game.scene.ui.getHandler() as SaveSlotSelectUiHandler; saveSlotSelectUiHandler.processInput(Button.ACTION); }); - await game.phaseInterceptor.whenAboutToRun(EncounterPhase); - expect(game.scene.getPlayerParty()[0].species.speciesId).toBe(SpeciesId.NIDORAN_M); + await game.phaseInterceptor.to("EncounterPhase", false); + expect(game.field.getPlayerPokemon().species.speciesId).toBe(SpeciesId.NIDORAN_M); }); }); diff --git a/test/ui/transfer-item.test.ts b/test/ui/transfer-item.test.ts index 0d101b5b4ef..8e42149acc3 100644 --- a/test/ui/transfer-item.test.ts +++ b/test/ui/transfer-item.test.ts @@ -72,8 +72,6 @@ describe("UI - Transfer Items", () => { expect( handler.optionsContainer.list.some(option => RegExp(/Lum Berry\[color.*(2)/).exec((option as BBCodeText).text)), ).toBe(true); - - game.phaseInterceptor.unlock(); }); await game.phaseInterceptor.to("SelectModifierPhase"); @@ -93,8 +91,6 @@ describe("UI - Transfer Items", () => { expect(handler.optionsContainer.list.some(option => (option as BBCodeText).text?.includes("Transfer"))).toBe( true, ); - - game.phaseInterceptor.unlock(); }); await game.phaseInterceptor.to("SelectModifierPhase"); diff --git a/test/ui/type-hints.test.ts b/test/ui/type-hints.test.ts index f1f27322a64..b5fe0d9585a 100644 --- a/test/ui/type-hints.test.ts +++ b/test/ui/type-hints.test.ts @@ -2,7 +2,6 @@ import { Button } from "#enums/buttons"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { UiMode } from "#enums/ui-mode"; -import { CommandPhase } from "#phases/command-phase"; import { GameManager } from "#test/test-utils/game-manager"; import type { MockText } from "#test/test-utils/mocks/mocks-container/mock-text"; import { FightUiHandler } from "#ui/fight-ui-handler"; @@ -46,7 +45,6 @@ describe("UI - Type Hints", () => { const { ui } = game.scene; const handler = ui.getHandler(); handler.processInput(Button.ACTION); // select "Fight" - game.phaseInterceptor.unlock(); }); game.onNextPrompt("CommandPhase", UiMode.FIGHT, () => { @@ -59,7 +57,7 @@ describe("UI - Type Hints", () => { expect.soft(dragonClawText.color).toBe("#929292"); ui.getHandler().processInput(Button.ACTION); }); - await game.phaseInterceptor.to(CommandPhase); + await game.phaseInterceptor.to("CommandPhase"); }); it("check status move color", async () => { @@ -71,7 +69,6 @@ describe("UI - Type Hints", () => { const { ui } = game.scene; const handler = ui.getHandler(); handler.processInput(Button.ACTION); // select "Fight" - game.phaseInterceptor.unlock(); }); game.onNextPrompt("CommandPhase", UiMode.FIGHT, () => { @@ -84,7 +81,7 @@ describe("UI - Type Hints", () => { expect.soft(growlText.color).toBe(undefined); ui.getHandler().processInput(Button.ACTION); }); - await game.phaseInterceptor.to(CommandPhase); + await game.phaseInterceptor.to("CommandPhase"); }); it("should show the proper hint for a move in doubles after one of the enemy pokemon flees", async () => { @@ -107,7 +104,6 @@ describe("UI - Type Hints", () => { const { ui } = game.scene; const handler = ui.getHandler(); handler.processInput(Button.ACTION); // select "Fight" - game.phaseInterceptor.unlock(); }); game.onNextPrompt("CommandPhase", UiMode.FIGHT, () => { @@ -121,6 +117,6 @@ describe("UI - Type Hints", () => { expect.soft(shadowBallText.color).toBe(undefined); ui.getHandler().processInput(Button.ACTION); }); - await game.phaseInterceptor.to(CommandPhase); + await game.phaseInterceptor.to("CommandPhase"); }); });