diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index b1543b2cb44..f2e17898334 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -20,6 +20,7 @@ permissions: jobs: create-release: if: github.repository == 'pagefaultgames/pokerogue' && (vars.BETA_DEPLOY_BRANCH == '' || ! startsWith(vars.BETA_DEPLOY_BRANCH, 'release')) + timeout-minutes: 10 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed for github cli commands runs-on: ubuntu-latest @@ -36,11 +37,13 @@ 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: @@ -48,8 +51,10 @@ jobs: # 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. - name: Overwrite RELEASE file run: | @@ -58,11 +63,14 @@ jobs: echo "Release v${{ github.event.inputs.versionName }}" > RELEASE git add RELEASE git commit -m "Stage release v${{ github.event.inputs.versionName }}" + - name: Push new branch 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="${{ 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 \ @@ -70,6 +78,7 @@ jobs: --title "Release v${{ github.event.inputs.versionName }} to main" \ --body "This PR is for the release of v${{ github.event.inputs.versionName }}, and was created automatically by the GitHub Actions workflow invoked by ${{ github.actor }}" \ --draft + - name: Create pull request to beta run: | gh pr create --base beta \ diff --git a/.github/workflows/deploy-beta.yml b/.github/workflows/deploy-beta.yml index 0894032c8ad..341999dcd45 100644 --- a/.github/workflows/deploy-beta.yml +++ b/.github/workflows/deploy-beta.yml @@ -12,6 +12,7 @@ on: jobs: deploy: if: github.repository == 'pagefaultgames/pokerogue' && github.ref_name == (vars.BETA_DEPLOY_BRANCH || 'beta') + timeout-minutes: 10 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0e7102a41dd..528906196e5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,6 +11,7 @@ on: jobs: deploy: if: github.repository == 'pagefaultgames/pokerogue' + timeout-minutes: 10 runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/github-pages.yml b/.github/workflows/github-pages.yml index 84d5964064f..b7b1aad5ae7 100644 --- a/.github/workflows/github-pages.yml +++ b/.github/workflows/github-pages.yml @@ -6,11 +6,13 @@ on: - main - beta - release + - 'hotfix*' pull_request: branches: - main - beta - release + - 'hotfix*' merge_group: types: [checks_requested] @@ -18,9 +20,12 @@ jobs: pages: name: Github Pages if: github.repository == 'pagefaultgames/pokerogue' + timeout-minutes: 10 runs-on: ubuntu-latest env: - api-dir: ./ + docs-dir: ./pokerogue_docs + # Only push docs when running on pushes to main/beta + DRY_RUN: ${{github.event_name != 'push' || (github.ref_name != 'beta' && github.ref_name != 'main')}} strategy: fail-fast: false @@ -42,7 +47,7 @@ jobs: with: version: 10 - - name: Setup Node 22.14.1 + - name: Setup Node uses: actions/setup-node@v4 with: node-version-file: "pokerogue_docs/.nvmrc" @@ -55,26 +60,26 @@ jobs: ref: gh-pages - name: Install Node.js dependencies - working-directory: ${{env.api-dir}} - run: | - cd pokerogue_docs - pnpm i + working-directory: ${{env.docs-dir}} + run: pnpm i - name: Generate Typedoc docs - working-directory: ${{env.api-dir}} - run: | - cd pokerogue_docs - pnpm exec typedoc --out /tmp/docs --githubPages false --entryPoints ./src/ + working-directory: ${{env.docs-dir}} + env: + REF_NAME: ${{github.ref_name}} + DRY_RUN: ${{env.DRY_RUN}} + run: pnpm typedoc - name: Commit & Push docs - if: github.event_name == 'push' + # env vars are stored as strings instead of booleans (hence why an explicit check is required) + if: ${{ env.DRY_RUN == 'false'}} run: | cd pokerogue_gh git config user.email "github-actions[bot]@users.noreply.github.com" git config user.name "github-actions[bot]" mkdir -p $GITHUB_REF_NAME rm -rf $GITHUB_REF_NAME/* - cp -r /tmp/docs/. $GITHUB_REF_NAME + cp -r /tmp/docs $GITHUB_REF_NAME git add $GITHUB_REF_NAME - git commit --allow-empty -m "[skip ci] Deploy docs" - git push \ No newline at end of file + git commit -m "[skip ci] Deploy docs" + git push diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index a5e8f96961e..08327ee3653 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -6,17 +6,20 @@ on: - main - beta - release + - 'hotfix*' pull_request: branches: - main - beta - release + - 'hotfix*' merge_group: types: [checks_requested] jobs: run-linters: name: Run linters + timeout-minutes: 10 runs-on: ubuntu-latest steps: diff --git a/.github/workflows/post-release-deleted.yml b/.github/workflows/post-release-deleted.yml index 65447e7826b..fe542365da4 100644 --- a/.github/workflows/post-release-deleted.yml +++ b/.github/workflows/post-release-deleted.yml @@ -6,6 +6,7 @@ jobs: # Set the BETA_DEPLOY_BRANCH variable to beta when a release branch is deleted update-release-var: if: github.repository == 'pagefaultgames/pokerogue' && github.event.ref_type == 'branch' && github.event.ref == 'release' + timeout-minutes: 5 runs-on: ubuntu-latest steps: - name: Set BETA_DEPLOY_BRANCH to beta diff --git a/.github/workflows/test-shard-template.yml b/.github/workflows/test-shard-template.yml index 124004f380f..79aea56bbd0 100644 --- a/.github/workflows/test-shard-template.yml +++ b/.github/workflows/test-shard-template.yml @@ -21,6 +21,7 @@ jobs: test: # We can't use dynmically named jobs until https://github.com/orgs/community/discussions/13261 is implemented name: Shard + timeout-minutes: 10 runs-on: ubuntu-latest if: ${{ !inputs.skip }} steps: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2b9f6dc9c0d..39506096298 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,17 +6,20 @@ on: - main - beta - release + - 'hotfix*' pull_request: branches: - main - beta - release + - 'hotfix*' merge_group: types: [checks_requested] workflow_dispatch: jobs: check-path-change-filter: + timeout-minutes: 5 runs-on: ubuntu-latest permissions: pull-requests: read @@ -35,6 +38,8 @@ jobs: name: Run Tests needs: check-path-change-filter strategy: + # don't stop upon 1 shard failing + fail-fast: false matrix: shard: [1, 2, 3, 4, 5] uses: ./.github/workflows/test-shard-template.yml diff --git a/README.md b/README.md index 1bb8c7772f3..cf70b5d9335 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ PokéRogue +![Discord Static Badge](https://img.shields.io/badge/Community_Discord-blurple?style=flat&logo=discord&logoSize=auto&labelColor=white&color=5865F2&link=https://discord.gg/pokerogue) +[![Docs Coverage Static Badge](https://pagefaultgames.github.io/pokerogue/beta/coverage.svg)](https://pagefaultgames.github.io/pokerogue/beta) +[![Testing Badge](https://github.com/pagefaultgames/pokerogue/actions/workflows/tests.yml/badge.svg)](https://github.com/pagefaultgames/pokerogue/actions/workflows/tests.yml) +[![License: GNU AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) + PokéRogue is a browser based Pokémon fangame heavily inspired by the roguelite genre. Battle endlessly while gathering stacking items, exploring many different biomes, fighting trainers, bosses, and more! # Contributing @@ -7,7 +12,7 @@ PokéRogue is a browser based Pokémon fangame heavily inspired by the roguelite See [CONTRIBUTING.md](./CONTRIBUTING.md), this includes instructions on how to set up the game locally. # 📝 Credits -> + > If this project contains assets you have produced and you do not see your name, **please** reach out, either [here on GitHub](https://github.com/pagefaultgames/pokerogue/issues/new) or via [Discord](https://discord.gg/pokerogue). Thank you to all the wonderful people that have contributed to the PokéRogue project! You can find the credits [here](./CREDITS.md). diff --git a/global.d.ts b/global.d.ts index 8b79d966e3c..92a883f40c9 100644 --- a/global.d.ts +++ b/global.d.ts @@ -18,3 +18,14 @@ declare global { call(this: T, thisArg: ThisParameterType, ...argArray: Parameters): ReturnType; } } + +// Global augments for `typedoc` to prevent TS from erroring when editing the config JS file +declare module "typedoc" { + export interface TypeDocOptionMap { + coverageLabel: string; + coverageColor: string; + coverageOutputPath: string; + coverageOutputType: "svg" | "json" | "all"; + coverageSvgWidth: number; + } +} diff --git a/package.json b/package.json index 93668f15c61..0620cf6a88c 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.11.0", + "version": "1.10.6", "type": "module", "scripts": { - "start": "vite", + "start:prod": "vite --mode production", + "start:beta": "vite --mode beta", "start:dev": "vite --mode development", "build": "vite build", "build:beta": "vite build --mode beta", @@ -18,7 +19,7 @@ "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", - "docs": "typedoc", + "typedoc": "typedoc", "depcruise": "depcruise src test", "postinstall": "lefthook install; git submodule update --init --recursive", "update-version:patch": "pnpm version patch --force --no-git-tag-version", @@ -41,6 +42,9 @@ "msw": "^2.10.4", "phaser3spectorjs": "^0.0.8", "typedoc": "^0.28.8", + "typedoc-github-theme": "^0.3.1", + "typedoc-plugin-coverage": "^4.0.1", + "typedoc-plugin-mdn-links": "^5.0.9", "typescript": "^5.8.3", "vite": "^7.0.6", "vite-tsconfig-paths": "^5.1.4", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c3b58a60f48..089689818ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -87,6 +87,15 @@ importers: typedoc: specifier: ^0.28.8 version: 0.28.8(typescript@5.8.3) + typedoc-github-theme: + specifier: ^0.3.1 + version: 0.3.1(typedoc@0.28.8(typescript@5.8.3)) + typedoc-plugin-coverage: + specifier: ^4.0.1 + version: 4.0.1(typedoc@0.28.8(typescript@5.8.3)) + typedoc-plugin-mdn-links: + specifier: ^5.0.9 + version: 5.0.9(typedoc@0.28.8(typescript@5.8.3)) typescript: specifier: ^5.8.3 version: 5.8.3 @@ -1789,6 +1798,23 @@ packages: resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==} engines: {node: '>=16'} + typedoc-github-theme@0.3.1: + resolution: {integrity: sha512-j6PmkAGmf/MGCzYjQcUH6jS9djPsNl/IoTXooxC+MoeMkBhbmPyKJlpR6Lw12BLoe2OYpYA2J1KMktUJXp/8Sw==} + engines: {node: '>=18.0.0'} + peerDependencies: + typedoc: ~0.28.0 + + typedoc-plugin-coverage@4.0.1: + resolution: {integrity: sha512-P1QBR5GJSfW3fDrpz4Vkd8z8lzWaBYjaHebRLk0u2Uga0oSFlPaqrCyiHzItBXxZX28aMlNlZwrUnsLgUgqA7g==} + engines: {node: '>= 18'} + peerDependencies: + typedoc: 0.28.x + + typedoc-plugin-mdn-links@5.0.9: + resolution: {integrity: sha512-kXssRKBhUd0JeHzFmxWVsGWVFR9WXafe70Y8Ed+MYH2Nu2647cqfGQN1OBKgvXpmAT8MTpACmUIQ7GnQnh1/iw==} + peerDependencies: + typedoc: 0.27.x || 0.28.x + typedoc@0.28.8: resolution: {integrity: sha512-16GfLopc8icHfdvqZDqdGBoS2AieIRP2rpf9mU+MgN+gGLyEQvAO0QgOa6NJ5QNmQi0LFrDY9in4F2fUNKgJKA==} engines: {node: '>= 18', pnpm: '>= 10'} @@ -3634,6 +3660,18 @@ snapshots: type-fest@4.41.0: {} + typedoc-github-theme@0.3.1(typedoc@0.28.8(typescript@5.8.3)): + dependencies: + typedoc: 0.28.8(typescript@5.8.3) + + typedoc-plugin-coverage@4.0.1(typedoc@0.28.8(typescript@5.8.3)): + dependencies: + typedoc: 0.28.8(typescript@5.8.3) + + typedoc-plugin-mdn-links@5.0.9(typedoc@0.28.8(typescript@5.8.3)): + dependencies: + typedoc: 0.28.8(typescript@5.8.3) + typedoc@0.28.8(typescript@5.8.3): dependencies: '@gerrit0/mini-shiki': 3.8.1 diff --git a/public/images/arenas/beach_b_2.png b/public/images/arenas/beach_b_2.png index 50c9be97b0d..6c3e89c1b25 100644 Binary files a/public/images/arenas/beach_b_2.png and b/public/images/arenas/beach_b_2.png differ diff --git a/public/images/arenas/cave_b_2.png b/public/images/arenas/cave_b_2.png index f76560e1f03..99c850ecdf6 100644 Binary files a/public/images/arenas/cave_b_2.png and b/public/images/arenas/cave_b_2.png differ diff --git a/public/images/arenas/factory_b_3.png b/public/images/arenas/factory_b_3.png index f2bb93128cf..e7716f0e168 100644 Binary files a/public/images/arenas/factory_b_3.png and b/public/images/arenas/factory_b_3.png differ diff --git a/public/images/arenas/forest_b.png b/public/images/arenas/forest_b.png index dcd1981a5e9..9f2cfc20c09 100644 Binary files a/public/images/arenas/forest_b.png and b/public/images/arenas/forest_b.png differ diff --git a/public/images/arenas/ice_cave_b_2.png b/public/images/arenas/ice_cave_b_2.png index d7e6fb1784e..636f4e95946 100644 Binary files a/public/images/arenas/ice_cave_b_2.png and b/public/images/arenas/ice_cave_b_2.png differ diff --git a/public/images/arenas/island_bg.png b/public/images/arenas/island_bg.png index e05c3afa775..8a8d703af5d 100644 Binary files a/public/images/arenas/island_bg.png and b/public/images/arenas/island_bg.png differ diff --git a/public/images/arenas/jungle_bg.png b/public/images/arenas/jungle_bg.png index e03de2a3223..4a8fa41fbb3 100644 Binary files a/public/images/arenas/jungle_bg.png and b/public/images/arenas/jungle_bg.png differ diff --git a/public/images/arenas/laboratory_b_2.png b/public/images/arenas/laboratory_b_2.png index fcd945b8b86..b5d73b8a9ed 100644 Binary files a/public/images/arenas/laboratory_b_2.png and b/public/images/arenas/laboratory_b_2.png differ diff --git a/public/images/arenas/laboratory_bg.png b/public/images/arenas/laboratory_bg.png index 0e64877c0b6..decb26240b3 100644 Binary files a/public/images/arenas/laboratory_bg.png and b/public/images/arenas/laboratory_bg.png differ diff --git a/public/images/arenas/lake_b_1.png b/public/images/arenas/lake_b_1.png index 5426dd1e8d9..8786fb6c728 100644 Binary files a/public/images/arenas/lake_b_1.png and b/public/images/arenas/lake_b_1.png differ diff --git a/public/images/arenas/lake_b_2.png b/public/images/arenas/lake_b_2.png index b08ccd7b8e4..454c9e89d29 100644 Binary files a/public/images/arenas/lake_b_2.png and b/public/images/arenas/lake_b_2.png differ diff --git a/public/images/arenas/metropolis_bg.png b/public/images/arenas/metropolis_bg.png index 374744f245e..b790221b323 100644 Binary files a/public/images/arenas/metropolis_bg.png and b/public/images/arenas/metropolis_bg.png differ diff --git a/public/images/arenas/plains_b_2.png b/public/images/arenas/plains_b_2.png index a35dbec9917..4d8d679d12f 100644 Binary files a/public/images/arenas/plains_b_2.png and b/public/images/arenas/plains_b_2.png differ diff --git a/public/images/arenas/plains_bg.png b/public/images/arenas/plains_bg.png index f2cbec9197c..9c0cff9b7dc 100644 Binary files a/public/images/arenas/plains_bg.png and b/public/images/arenas/plains_bg.png differ diff --git a/public/images/arenas/snowy_forest_b_3.png b/public/images/arenas/snowy_forest_b_3.png index 14c8f4c64aa..d8c89496d14 100644 Binary files a/public/images/arenas/snowy_forest_b_3.png and b/public/images/arenas/snowy_forest_b_3.png differ diff --git a/public/images/arenas/snowy_forest_bg.png b/public/images/arenas/snowy_forest_bg.png index b0dcc3ddfc5..62ff03f5b1c 100644 Binary files a/public/images/arenas/snowy_forest_bg.png and b/public/images/arenas/snowy_forest_bg.png differ diff --git a/public/images/arenas/wasteland_b_1.png b/public/images/arenas/wasteland_b_1.png index d10a7f27699..7f62b29f9a8 100644 Binary files a/public/images/arenas/wasteland_b_1.png and b/public/images/arenas/wasteland_b_1.png differ diff --git a/public/images/arenas/wasteland_b_3.png b/public/images/arenas/wasteland_b_3.png index cdc5a2bdd50..73a5b283861 100644 Binary files a/public/images/arenas/wasteland_b_3.png and b/public/images/arenas/wasteland_b_3.png differ diff --git a/public/images/battle_anims/PRAS- Pulverizing Pancake BG2.png b/public/images/battle_anims/PRAS- Pulverizing Pancake BG2.png index 44b50a6d385..4c55dd5f1c8 100644 Binary files a/public/images/battle_anims/PRAS- Pulverizing Pancake BG2.png and b/public/images/battle_anims/PRAS- Pulverizing Pancake BG2.png differ diff --git a/public/images/battle_anims/PRAS- Pulverizing Pancake.png b/public/images/battle_anims/PRAS- Pulverizing Pancake.png index 519a52c63c6..b284493c6da 100644 Binary files a/public/images/battle_anims/PRAS- Pulverizing Pancake.png and b/public/images/battle_anims/PRAS- Pulverizing Pancake.png differ diff --git a/public/images/battle_anims/PRAS- Spectral thief BG.png b/public/images/battle_anims/PRAS- Spectral thief BG.png index 35fc434fdca..92c356c5ec5 100644 Binary files a/public/images/battle_anims/PRAS- Spectral thief BG.png and b/public/images/battle_anims/PRAS- Spectral thief BG.png differ diff --git a/public/images/egg/egg_crack.png b/public/images/egg/egg_crack.png index 9d553ebf378..f5b5ee7b7e1 100644 Binary files a/public/images/egg/egg_crack.png and b/public/images/egg/egg_crack.png differ diff --git a/public/images/items.png b/public/images/items.png index a4ca454a153..ecc8d42daea 100644 Binary files a/public/images/items.png and b/public/images/items.png differ diff --git a/public/images/items/common_egg.png b/public/images/items/common_egg.png index 5eccff2f690..c449611d532 100644 Binary files a/public/images/items/common_egg.png and b/public/images/items/common_egg.png differ diff --git a/public/images/items/great_ribbon.png b/public/images/items/great_ribbon.png index 4db20f29c1f..284ee6a3b3b 100644 Binary files a/public/images/items/great_ribbon.png and b/public/images/items/great_ribbon.png differ diff --git a/public/images/mystery-encounters/fun_and_games_wobbuffet.png b/public/images/mystery-encounters/fun_and_games_wobbuffet.png index 71997be5692..5d61512ea78 100644 Binary files a/public/images/mystery-encounters/fun_and_games_wobbuffet.png and b/public/images/mystery-encounters/fun_and_games_wobbuffet.png differ diff --git a/public/images/mystery-encounters/mysterious_chest_blue.png b/public/images/mystery-encounters/mysterious_chest_blue.png index f959db13aa7..6fa3a7c5475 100644 Binary files a/public/images/mystery-encounters/mysterious_chest_blue.png and b/public/images/mystery-encounters/mysterious_chest_blue.png differ diff --git a/public/images/ui/champion_ribbon.png b/public/images/ui/champion_ribbon.png index b188f4c92d2..a19bb01279b 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 b69efbb8f88..4bd1cb8ea2d 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 fd0e1f77480..207ade56c19 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 4b0523f7f64..29a9503059d 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 92b6f4cf8c7..52cde028406 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/legacy/champion_ribbon.png b/public/images/ui/legacy/champion_ribbon.png index b188f4c92d2..a19bb01279b 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 b69efbb8f88..4bd1cb8ea2d 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 fd0e1f77480..207ade56c19 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 4b0523f7f64..29a9503059d 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 92b6f4cf8c7..52cde028406 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/pokedex_summary_bg.png b/public/images/ui/legacy/pokedex_summary_bg.png index 0f8fed843c9..62369eaa248 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/starter_select_bg.png b/public/images/ui/legacy/starter_select_bg.png index 501e892969e..09d21d4a630 100644 Binary files a/public/images/ui/legacy/starter_select_bg.png and b/public/images/ui/legacy/starter_select_bg.png differ diff --git a/public/images/ui/legacy/summary_bg.png b/public/images/ui/legacy/summary_bg.png index 668a7438bf0..b08bd406a81 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.png b/public/images/ui/legacy/summary_moves.png index ab909588160..abb499fdbb0 100644 Binary files a/public/images/ui/legacy/summary_moves.png and b/public/images/ui/legacy/summary_moves.png differ diff --git a/public/images/ui/legacy/summary_moves_effect.png b/public/images/ui/legacy/summary_moves_effect.png index 61567c9749b..f12e7e523b8 100644 Binary files a/public/images/ui/legacy/summary_moves_effect.png and b/public/images/ui/legacy/summary_moves_effect.png differ diff --git a/public/images/ui/legacy/summary_profile.png b/public/images/ui/legacy/summary_profile.png index d8cfebb000e..e2c678a3206 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 deleted file mode 100644 index f839a6249f8..00000000000 Binary files a/public/images/ui/legacy/summary_profile_ability.png and /dev/null differ diff --git a/public/images/ui/legacy/summary_profile_passive.png b/public/images/ui/legacy/summary_profile_passive.png deleted file mode 100644 index 1ff9ad8e09a..00000000000 Binary files a/public/images/ui/legacy/summary_profile_passive.png and /dev/null differ diff --git a/public/images/ui/legacy/summary_stats.png b/public/images/ui/legacy/summary_stats.png index 1da361f6157..773661cce07 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/legacy/text_images/ca/summary/summary_dexnb_label_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_dexnb_label_ca.png new file mode 100644 index 00000000000..a457468d8d0 Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_dexnb_label_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_dexnb_label_overlay_shiny_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_dexnb_label_overlay_shiny_ca.png new file mode 100644 index 00000000000..3277a28a59b Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_dexnb_label_overlay_shiny_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_moves_descriptions_title_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_moves_descriptions_title_ca.png new file mode 100644 index 00000000000..a37aad953cc Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_moves_descriptions_title_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_moves_effect_title_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_moves_effect_title_ca.png new file mode 100644 index 00000000000..ca66436eca6 Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_moves_effect_title_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_moves_moves_title_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_moves_moves_title_ca.png new file mode 100644 index 00000000000..71a6889da53 Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_moves_moves_title_ca.png differ diff --git a/public/images/ui/legacy/summary_moves_overlay_pp.png b/public/images/ui/legacy/text_images/ca/summary/summary_moves_overlay_pp_ca.png similarity index 100% rename from public/images/ui/legacy/summary_moves_overlay_pp.png rename to public/images/ui/legacy/text_images/ca/summary/summary_moves_overlay_pp_ca.png diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_profile_ability_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_profile_ability_ca.png new file mode 100644 index 00000000000..2d9e8ac317d Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_profile_ability_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_profile_memo_title_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_profile_memo_title_ca.png new file mode 100644 index 00000000000..b7ef7c91fc5 Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_profile_memo_title_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_profile_passive_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_profile_passive_ca.png new file mode 100644 index 00000000000..a072b663d25 Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_profile_passive_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_profile_profile_title_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_profile_profile_title_ca.png new file mode 100644 index 00000000000..a5ed0e3e169 Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_profile_profile_title_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_stats_exp_title_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_stats_exp_title_ca.png new file mode 100644 index 00000000000..e7ac7268b54 Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_stats_exp_title_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_stats_expbar_title_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_stats_expbar_title_ca.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_stats_expbar_title_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_stats_item_title_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_stats_item_title_ca.png new file mode 100644 index 00000000000..c13189fc816 Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_stats_item_title_ca.png differ diff --git a/public/images/ui/legacy/text_images/ca/summary/summary_stats_stats_title_ca.png b/public/images/ui/legacy/text_images/ca/summary/summary_stats_stats_title_ca.png new file mode 100644 index 00000000000..426848af866 Binary files /dev/null and b/public/images/ui/legacy/text_images/ca/summary/summary_stats_stats_title_ca.png differ diff --git a/public/images/ui/legacy/summary_tabs_1.png b/public/images/ui/legacy/text_images/ca/summary/summary_tabs_1_ca.png similarity index 100% rename from public/images/ui/legacy/summary_tabs_1.png rename to public/images/ui/legacy/text_images/ca/summary/summary_tabs_1_ca.png diff --git a/public/images/ui/legacy/summary_tabs_2.png b/public/images/ui/legacy/text_images/ca/summary/summary_tabs_2_ca.png similarity index 100% rename from public/images/ui/legacy/summary_tabs_2.png rename to public/images/ui/legacy/text_images/ca/summary/summary_tabs_2_ca.png diff --git a/public/images/ui/legacy/summary_tabs_3.png b/public/images/ui/legacy/text_images/ca/summary/summary_tabs_3_ca.png similarity index 100% rename from public/images/ui/legacy/summary_tabs_3.png rename to public/images/ui/legacy/text_images/ca/summary/summary_tabs_3_ca.png diff --git a/public/images/ui/legacy/text_images/da/summary/summary_dexnb_label_da.png b/public/images/ui/legacy/text_images/da/summary/summary_dexnb_label_da.png new file mode 100644 index 00000000000..ef081f493f3 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_dexnb_label_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_dexnb_label_overlay_shiny_da.png b/public/images/ui/legacy/text_images/da/summary/summary_dexnb_label_overlay_shiny_da.png new file mode 100644 index 00000000000..92c2412f426 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_dexnb_label_overlay_shiny_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_moves_descriptions_title_da.png b/public/images/ui/legacy/text_images/da/summary/summary_moves_descriptions_title_da.png new file mode 100644 index 00000000000..79b16227bfe Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_moves_descriptions_title_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_moves_effect_title_da.png b/public/images/ui/legacy/text_images/da/summary/summary_moves_effect_title_da.png new file mode 100644 index 00000000000..f2ac04e62c4 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_moves_effect_title_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_moves_moves_title_da.png b/public/images/ui/legacy/text_images/da/summary/summary_moves_moves_title_da.png new file mode 100644 index 00000000000..f1732e3e2c0 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_moves_moves_title_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_moves_overlay_pp_da.png b/public/images/ui/legacy/text_images/da/summary/summary_moves_overlay_pp_da.png new file mode 100644 index 00000000000..6cc0a2a6831 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_moves_overlay_pp_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_profile_ability_da.png b/public/images/ui/legacy/text_images/da/summary/summary_profile_ability_da.png new file mode 100644 index 00000000000..206b65c6cdd Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_profile_ability_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_profile_memo_title_da.png b/public/images/ui/legacy/text_images/da/summary/summary_profile_memo_title_da.png new file mode 100644 index 00000000000..48886d25e39 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_profile_memo_title_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_profile_passive_da.png b/public/images/ui/legacy/text_images/da/summary/summary_profile_passive_da.png new file mode 100644 index 00000000000..681ae3f1b5e Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_profile_passive_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_profile_profile_title_da.png b/public/images/ui/legacy/text_images/da/summary/summary_profile_profile_title_da.png new file mode 100644 index 00000000000..83b8a1d5e99 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_profile_profile_title_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_stats_exp_title_da.png b/public/images/ui/legacy/text_images/da/summary/summary_stats_exp_title_da.png new file mode 100644 index 00000000000..feae0c9cb90 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_stats_exp_title_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_stats_expbar_title_da.png b/public/images/ui/legacy/text_images/da/summary/summary_stats_expbar_title_da.png new file mode 100644 index 00000000000..78bfe5d9735 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_stats_expbar_title_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_stats_item_title_da.png b/public/images/ui/legacy/text_images/da/summary/summary_stats_item_title_da.png new file mode 100644 index 00000000000..2cbce6c3dcf Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_stats_item_title_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_stats_stats_title_da.png b/public/images/ui/legacy/text_images/da/summary/summary_stats_stats_title_da.png new file mode 100644 index 00000000000..ff97416c7ed Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_stats_stats_title_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_tabs_1_da.png b/public/images/ui/legacy/text_images/da/summary/summary_tabs_1_da.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_tabs_1_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_tabs_2_da.png b/public/images/ui/legacy/text_images/da/summary/summary_tabs_2_da.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_tabs_2_da.png differ diff --git a/public/images/ui/legacy/text_images/da/summary/summary_tabs_3_da.png b/public/images/ui/legacy/text_images/da/summary/summary_tabs_3_da.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/da/summary/summary_tabs_3_da.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_dexnb_label_de.png b/public/images/ui/legacy/text_images/de/summary/summary_dexnb_label_de.png new file mode 100644 index 00000000000..ef081f493f3 Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_dexnb_label_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_dexnb_label_overlay_shiny_de.png b/public/images/ui/legacy/text_images/de/summary/summary_dexnb_label_overlay_shiny_de.png new file mode 100644 index 00000000000..92c2412f426 Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_dexnb_label_overlay_shiny_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_moves_descriptions_title_de.png b/public/images/ui/legacy/text_images/de/summary/summary_moves_descriptions_title_de.png new file mode 100644 index 00000000000..ea4827c081d Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_moves_descriptions_title_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_moves_effect_title_de.png b/public/images/ui/legacy/text_images/de/summary/summary_moves_effect_title_de.png new file mode 100644 index 00000000000..951e9281839 Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_moves_effect_title_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_moves_moves_title_de.png b/public/images/ui/legacy/text_images/de/summary/summary_moves_moves_title_de.png new file mode 100644 index 00000000000..d5e28d3dfe7 Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_moves_moves_title_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_moves_overlay_pp_de.png b/public/images/ui/legacy/text_images/de/summary/summary_moves_overlay_pp_de.png new file mode 100644 index 00000000000..ba23731775d Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_moves_overlay_pp_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_profile_ability_de.png b/public/images/ui/legacy/text_images/de/summary/summary_profile_ability_de.png new file mode 100644 index 00000000000..2b6bd055555 Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_profile_ability_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_profile_memo_title_de.png b/public/images/ui/legacy/text_images/de/summary/summary_profile_memo_title_de.png new file mode 100644 index 00000000000..089668218fa Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_profile_memo_title_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_profile_passive_de.png b/public/images/ui/legacy/text_images/de/summary/summary_profile_passive_de.png new file mode 100644 index 00000000000..681ae3f1b5e Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_profile_passive_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_profile_profile_title_de.png b/public/images/ui/legacy/text_images/de/summary/summary_profile_profile_title_de.png new file mode 100644 index 00000000000..83b8a1d5e99 Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_profile_profile_title_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_stats_exp_title_de.png b/public/images/ui/legacy/text_images/de/summary/summary_stats_exp_title_de.png new file mode 100644 index 00000000000..fa702b4c223 Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_stats_exp_title_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_stats_expbar_title_de.png b/public/images/ui/legacy/text_images/de/summary/summary_stats_expbar_title_de.png new file mode 100644 index 00000000000..78bfe5d9735 Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_stats_expbar_title_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_stats_item_title_de.png b/public/images/ui/legacy/text_images/de/summary/summary_stats_item_title_de.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_stats_item_title_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_stats_stats_title_de.png b/public/images/ui/legacy/text_images/de/summary/summary_stats_stats_title_de.png new file mode 100644 index 00000000000..87438a5bd4f Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_stats_stats_title_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_tabs_1_de.png b/public/images/ui/legacy/text_images/de/summary/summary_tabs_1_de.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_tabs_1_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_tabs_2_de.png b/public/images/ui/legacy/text_images/de/summary/summary_tabs_2_de.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_tabs_2_de.png differ diff --git a/public/images/ui/legacy/text_images/de/summary/summary_tabs_3_de.png b/public/images/ui/legacy/text_images/de/summary/summary_tabs_3_de.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/de/summary/summary_tabs_3_de.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_dexnb_label.png b/public/images/ui/legacy/text_images/en/summary/summary_dexnb_label.png new file mode 100644 index 00000000000..eab90a91c7f Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_dexnb_label.png differ diff --git a/public/images/ui/legacy/summary_overlay_shiny.png b/public/images/ui/legacy/text_images/en/summary/summary_dexnb_label_overlay_shiny.png similarity index 100% rename from public/images/ui/legacy/summary_overlay_shiny.png rename to public/images/ui/legacy/text_images/en/summary/summary_dexnb_label_overlay_shiny.png diff --git a/public/images/ui/legacy/text_images/en/summary/summary_moves_descriptions_title.png b/public/images/ui/legacy/text_images/en/summary/summary_moves_descriptions_title.png new file mode 100644 index 00000000000..3d2b4d08376 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_moves_descriptions_title.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_moves_effect_title.png b/public/images/ui/legacy/text_images/en/summary/summary_moves_effect_title.png new file mode 100644 index 00000000000..55fb0efd832 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_moves_effect_title.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_moves_moves_title.png b/public/images/ui/legacy/text_images/en/summary/summary_moves_moves_title.png new file mode 100644 index 00000000000..d869ab4e311 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_moves_moves_title.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_moves_overlay_pp.png b/public/images/ui/legacy/text_images/en/summary/summary_moves_overlay_pp.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_moves_overlay_pp.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_profile_ability.png b/public/images/ui/legacy/text_images/en/summary/summary_profile_ability.png new file mode 100644 index 00000000000..6600db26802 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_profile_ability.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_profile_memo_title.png b/public/images/ui/legacy/text_images/en/summary/summary_profile_memo_title.png new file mode 100644 index 00000000000..14cdf099044 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_profile_memo_title.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_profile_passive.png b/public/images/ui/legacy/text_images/en/summary/summary_profile_passive.png new file mode 100644 index 00000000000..66f56ff435e Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_profile_passive.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_profile_profile_title.png b/public/images/ui/legacy/text_images/en/summary/summary_profile_profile_title.png new file mode 100644 index 00000000000..8d4f82df3b3 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_profile_profile_title.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_stats_exp_title.png b/public/images/ui/legacy/text_images/en/summary/summary_stats_exp_title.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_stats_exp_title.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_stats_expbar_title.png b/public/images/ui/legacy/text_images/en/summary/summary_stats_expbar_title.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_stats_expbar_title.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_stats_item_title.png b/public/images/ui/legacy/text_images/en/summary/summary_stats_item_title.png new file mode 100644 index 00000000000..5752b28288c Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_stats_item_title.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_stats_stats_title.png b/public/images/ui/legacy/text_images/en/summary/summary_stats_stats_title.png new file mode 100644 index 00000000000..5531819ef66 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_stats_stats_title.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_tabs_1.png b/public/images/ui/legacy/text_images/en/summary/summary_tabs_1.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_tabs_1.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_tabs_2.png b/public/images/ui/legacy/text_images/en/summary/summary_tabs_2.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_tabs_2.png differ diff --git a/public/images/ui/legacy/text_images/en/summary/summary_tabs_3.png b/public/images/ui/legacy/text_images/en/summary/summary_tabs_3.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/en/summary/summary_tabs_3.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_dexnb_label_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_dexnb_label_es-ES.png new file mode 100644 index 00000000000..a457468d8d0 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_dexnb_label_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_dexnb_label_overlay_shiny_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_dexnb_label_overlay_shiny_es-ES.png new file mode 100644 index 00000000000..3277a28a59b Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_dexnb_label_overlay_shiny_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_descriptions_title_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_descriptions_title_es-ES.png new file mode 100644 index 00000000000..ffcae31894d Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_descriptions_title_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_effect_title_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_effect_title_es-ES.png new file mode 100644 index 00000000000..50ce2f51d6f Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_effect_title_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_moves_title_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_moves_title_es-ES.png new file mode 100644 index 00000000000..ffca8bdfa10 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_moves_title_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_overlay_pp_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_overlay_pp_es-ES.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_moves_overlay_pp_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_ability_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_ability_es-ES.png new file mode 100644 index 00000000000..b1b1a84ddcf Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_ability_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_memo_title_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_memo_title_es-ES.png new file mode 100644 index 00000000000..e837a58e4f9 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_memo_title_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_passive_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_passive_es-ES.png new file mode 100644 index 00000000000..885453e3e98 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_passive_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_profile_title_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_profile_title_es-ES.png new file mode 100644 index 00000000000..51ba9300dab Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_profile_profile_title_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_exp_title_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_exp_title_es-ES.png new file mode 100644 index 00000000000..7c8a80f0627 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_exp_title_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_expbar_title_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_expbar_title_es-ES.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_expbar_title_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_item_title_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_item_title_es-ES.png new file mode 100644 index 00000000000..15fdb806125 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_item_title_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_stats_title_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_stats_title_es-ES.png new file mode 100644 index 00000000000..2233461522c Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_stats_stats_title_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_tabs_1_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_tabs_1_es-ES.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_tabs_1_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_tabs_2_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_tabs_2_es-ES.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_tabs_2_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-ES/summary/summary_tabs_3_es-ES.png b/public/images/ui/legacy/text_images/es-ES/summary/summary_tabs_3_es-ES.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-ES/summary/summary_tabs_3_es-ES.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_dexnb_label_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_dexnb_label_es-MX.png new file mode 100644 index 00000000000..a457468d8d0 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_dexnb_label_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_dexnb_label_overlay_shiny_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_dexnb_label_overlay_shiny_es-MX.png new file mode 100644 index 00000000000..3277a28a59b Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_dexnb_label_overlay_shiny_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_descriptions_title_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_descriptions_title_es-MX.png new file mode 100644 index 00000000000..ffcae31894d Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_descriptions_title_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_effect_title_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_effect_title_es-MX.png new file mode 100644 index 00000000000..50ce2f51d6f Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_effect_title_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_moves_title_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_moves_title_es-MX.png new file mode 100644 index 00000000000..ffca8bdfa10 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_moves_title_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_overlay_pp_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_overlay_pp_es-MX.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_moves_overlay_pp_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_ability_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_ability_es-MX.png new file mode 100644 index 00000000000..b1b1a84ddcf Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_ability_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_memo_title_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_memo_title_es-MX.png new file mode 100644 index 00000000000..e837a58e4f9 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_memo_title_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_passive_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_passive_es-MX.png new file mode 100644 index 00000000000..885453e3e98 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_passive_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_profile_title_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_profile_title_es-MX.png new file mode 100644 index 00000000000..51ba9300dab Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_profile_profile_title_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_exp_title_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_exp_title_es-MX.png new file mode 100644 index 00000000000..7c8a80f0627 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_exp_title_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_expbar_title_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_expbar_title_es-MX.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_expbar_title_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_item_title_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_item_title_es-MX.png new file mode 100644 index 00000000000..15fdb806125 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_item_title_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_stats_title_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_stats_title_es-MX.png new file mode 100644 index 00000000000..2233461522c Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_stats_stats_title_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_tabs_1_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_tabs_1_es-MX.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_tabs_1_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_tabs_2_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_tabs_2_es-MX.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_tabs_2_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/es-MX/summary/summary_tabs_3_es-MX.png b/public/images/ui/legacy/text_images/es-MX/summary/summary_tabs_3_es-MX.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/es-MX/summary/summary_tabs_3_es-MX.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_dexnb_label_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_dexnb_label_fr.png new file mode 100644 index 00000000000..5477e3385a8 Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_dexnb_label_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_dexnb_label_overlay_shiny_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_dexnb_label_overlay_shiny_fr.png new file mode 100644 index 00000000000..1640e46caa0 Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_dexnb_label_overlay_shiny_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_moves_descriptions_title_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_moves_descriptions_title_fr.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_moves_descriptions_title_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_moves_effect_title_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_moves_effect_title_fr.png new file mode 100644 index 00000000000..49f4e11096a Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_moves_effect_title_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_moves_moves_title_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_moves_moves_title_fr.png new file mode 100644 index 00000000000..1fd7d72c307 Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_moves_moves_title_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_moves_overlay_pp_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_moves_overlay_pp_fr.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_moves_overlay_pp_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_profile_ability_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_profile_ability_fr.png new file mode 100644 index 00000000000..3354b40adfe Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_profile_ability_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_profile_memo_title_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_profile_memo_title_fr.png new file mode 100644 index 00000000000..54c6beb4428 Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_profile_memo_title_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_profile_passive_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_profile_passive_fr.png new file mode 100644 index 00000000000..f5d2c98a21c Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_profile_passive_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_profile_profile_title_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_profile_profile_title_fr.png new file mode 100644 index 00000000000..bccba2d87df Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_profile_profile_title_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_stats_exp_title_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_stats_exp_title_fr.png new file mode 100644 index 00000000000..32d41d44be4 Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_stats_exp_title_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_stats_expbar_title_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_stats_expbar_title_fr.png new file mode 100644 index 00000000000..da999975932 Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_stats_expbar_title_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_stats_item_title_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_stats_item_title_fr.png new file mode 100644 index 00000000000..45c10e8c907 Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_stats_item_title_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_stats_stats_title_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_stats_stats_title_fr.png new file mode 100644 index 00000000000..63fe6a694af Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_stats_stats_title_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_tabs_1_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_tabs_1_fr.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_tabs_1_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_tabs_2_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_tabs_2_fr.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_tabs_2_fr.png differ diff --git a/public/images/ui/legacy/text_images/fr/summary/summary_tabs_3_fr.png b/public/images/ui/legacy/text_images/fr/summary/summary_tabs_3_fr.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/fr/summary/summary_tabs_3_fr.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_dexnb_label_it.png b/public/images/ui/legacy/text_images/it/summary/summary_dexnb_label_it.png new file mode 100644 index 00000000000..5477e3385a8 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_dexnb_label_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_dexnb_label_overlay_shiny_it.png b/public/images/ui/legacy/text_images/it/summary/summary_dexnb_label_overlay_shiny_it.png new file mode 100644 index 00000000000..1640e46caa0 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_dexnb_label_overlay_shiny_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_moves_descriptions_title_it.png b/public/images/ui/legacy/text_images/it/summary/summary_moves_descriptions_title_it.png new file mode 100644 index 00000000000..e0bf21396e5 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_moves_descriptions_title_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_moves_effect_title_it.png b/public/images/ui/legacy/text_images/it/summary/summary_moves_effect_title_it.png new file mode 100644 index 00000000000..99f9dfeb2c3 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_moves_effect_title_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_moves_moves_title_it.png b/public/images/ui/legacy/text_images/it/summary/summary_moves_moves_title_it.png new file mode 100644 index 00000000000..e56e3f4b336 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_moves_moves_title_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_moves_overlay_pp_it.png b/public/images/ui/legacy/text_images/it/summary/summary_moves_overlay_pp_it.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_moves_overlay_pp_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_profile_ability_it.png b/public/images/ui/legacy/text_images/it/summary/summary_profile_ability_it.png new file mode 100644 index 00000000000..bb915da37ee Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_profile_ability_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_profile_memo_title_it.png b/public/images/ui/legacy/text_images/it/summary/summary_profile_memo_title_it.png new file mode 100644 index 00000000000..0c81cd56f06 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_profile_memo_title_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_profile_passive_it.png b/public/images/ui/legacy/text_images/it/summary/summary_profile_passive_it.png new file mode 100644 index 00000000000..a072b663d25 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_profile_passive_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_profile_profile_title_it.png b/public/images/ui/legacy/text_images/it/summary/summary_profile_profile_title_it.png new file mode 100644 index 00000000000..169b0a7b8e7 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_profile_profile_title_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_stats_exp_title_it.png b/public/images/ui/legacy/text_images/it/summary/summary_stats_exp_title_it.png new file mode 100644 index 00000000000..a3a1aa4c402 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_stats_exp_title_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_stats_expbar_title_it.png b/public/images/ui/legacy/text_images/it/summary/summary_stats_expbar_title_it.png new file mode 100644 index 00000000000..aa8eee71613 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_stats_expbar_title_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_stats_item_title_it.png b/public/images/ui/legacy/text_images/it/summary/summary_stats_item_title_it.png new file mode 100644 index 00000000000..a93695a48c8 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_stats_item_title_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_stats_stats_title_it.png b/public/images/ui/legacy/text_images/it/summary/summary_stats_stats_title_it.png new file mode 100644 index 00000000000..998db7fc7e3 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_stats_stats_title_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_tabs_1_it.png b/public/images/ui/legacy/text_images/it/summary/summary_tabs_1_it.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_tabs_1_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_tabs_2_it.png b/public/images/ui/legacy/text_images/it/summary/summary_tabs_2_it.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_tabs_2_it.png differ diff --git a/public/images/ui/legacy/text_images/it/summary/summary_tabs_3_it.png b/public/images/ui/legacy/text_images/it/summary/summary_tabs_3_it.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/it/summary/summary_tabs_3_it.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_dexnb_label_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_dexnb_label_ja.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_dexnb_label_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_dexnb_label_overlay_shiny_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_dexnb_label_overlay_shiny_ja.png new file mode 100644 index 00000000000..bb2436738a8 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_dexnb_label_overlay_shiny_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_moves_descriptions_title_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_moves_descriptions_title_ja.png new file mode 100644 index 00000000000..d844e844244 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_moves_descriptions_title_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_moves_effect_title_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_moves_effect_title_ja.png new file mode 100644 index 00000000000..a75452f1299 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_moves_effect_title_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_moves_moves_title_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_moves_moves_title_ja.png new file mode 100644 index 00000000000..6492c3ecf7c Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_moves_moves_title_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_moves_overlay_pp_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_moves_overlay_pp_ja.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_moves_overlay_pp_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_profile_ability_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_profile_ability_ja.png new file mode 100644 index 00000000000..6c82a863a69 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_profile_ability_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_profile_memo_title_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_profile_memo_title_ja.png new file mode 100644 index 00000000000..3f5a4536817 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_profile_memo_title_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_profile_passive_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_profile_passive_ja.png new file mode 100644 index 00000000000..3bfed88c7da Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_profile_passive_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_profile_profile_title_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_profile_profile_title_ja.png new file mode 100644 index 00000000000..a05cba49247 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_profile_profile_title_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_stats_exp_title_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_stats_exp_title_ja.png new file mode 100644 index 00000000000..0bc237a7e6b Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_stats_exp_title_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_stats_expbar_title_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_stats_expbar_title_ja.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_stats_expbar_title_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_stats_item_title_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_stats_item_title_ja.png new file mode 100644 index 00000000000..114b4d7fd3f Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_stats_item_title_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_stats_stats_title_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_stats_stats_title_ja.png new file mode 100644 index 00000000000..c9f2e28fb07 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_stats_stats_title_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_tabs_1_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_tabs_1_ja.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_tabs_1_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_tabs_2_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_tabs_2_ja.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_tabs_2_ja.png differ diff --git a/public/images/ui/legacy/text_images/ja/summary/summary_tabs_3_ja.png b/public/images/ui/legacy/text_images/ja/summary/summary_tabs_3_ja.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/ja/summary/summary_tabs_3_ja.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_dexnb_label_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_dexnb_label_ko.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_dexnb_label_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_dexnb_label_overlay_shiny_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_dexnb_label_overlay_shiny_ko.png new file mode 100644 index 00000000000..bb2436738a8 Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_dexnb_label_overlay_shiny_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_moves_descriptions_title_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_moves_descriptions_title_ko.png new file mode 100644 index 00000000000..350bd607aed Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_moves_descriptions_title_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_moves_effect_title_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_moves_effect_title_ko.png new file mode 100644 index 00000000000..f90ac18fc4e Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_moves_effect_title_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_moves_moves_title_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_moves_moves_title_ko.png new file mode 100644 index 00000000000..d020d8a77cb Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_moves_moves_title_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_moves_overlay_pp_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_moves_overlay_pp_ko.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_moves_overlay_pp_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_profile_ability_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_profile_ability_ko.png new file mode 100644 index 00000000000..cdeafaf486e Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_profile_ability_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_profile_memo_title_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_profile_memo_title_ko.png new file mode 100644 index 00000000000..7af960fe1df Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_profile_memo_title_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_profile_passive_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_profile_passive_ko.png new file mode 100644 index 00000000000..34a13ffe836 Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_profile_passive_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_profile_profile_title_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_profile_profile_title_ko.png new file mode 100644 index 00000000000..deb57b96715 Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_profile_profile_title_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_stats_exp_title_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_stats_exp_title_ko.png new file mode 100644 index 00000000000..af0cb3afab8 Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_stats_exp_title_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_stats_expbar_title_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_stats_expbar_title_ko.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_stats_expbar_title_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_stats_item_title_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_stats_item_title_ko.png new file mode 100644 index 00000000000..6be5909e5f0 Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_stats_item_title_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_stats_stats_title_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_stats_stats_title_ko.png new file mode 100644 index 00000000000..371c2be4976 Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_stats_stats_title_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_tabs_1_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_tabs_1_ko.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_tabs_1_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_tabs_2_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_tabs_2_ko.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_tabs_2_ko.png differ diff --git a/public/images/ui/legacy/text_images/ko/summary/summary_tabs_3_ko.png b/public/images/ui/legacy/text_images/ko/summary/summary_tabs_3_ko.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/ko/summary/summary_tabs_3_ko.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_dexnb_label_overlay_shiny_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_dexnb_label_overlay_shiny_pt-BR.png new file mode 100644 index 00000000000..3277a28a59b Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_dexnb_label_overlay_shiny_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_dexnb_label_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_dexnb_label_pt-BR.png new file mode 100644 index 00000000000..5477e3385a8 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_dexnb_label_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_descriptions_title_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_descriptions_title_pt-BR.png new file mode 100644 index 00000000000..8d888143663 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_descriptions_title_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_effect_title_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_effect_title_pt-BR.png new file mode 100644 index 00000000000..83190955f2c Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_effect_title_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_moves_title_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_moves_title_pt-BR.png new file mode 100644 index 00000000000..0a2d1657750 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_moves_title_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_overlay_pp_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_overlay_pp_pt-BR.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_moves_overlay_pp_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_ability_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_ability_pt-BR.png new file mode 100644 index 00000000000..28fbb5a8be9 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_ability_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_memo_title_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_memo_title_pt-BR.png new file mode 100644 index 00000000000..b7ef7c91fc5 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_memo_title_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_passive_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_passive_pt-BR.png new file mode 100644 index 00000000000..11616a74287 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_passive_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_profile_title_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_profile_title_pt-BR.png new file mode 100644 index 00000000000..a5ed0e3e169 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_profile_profile_title_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_exp_title_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_exp_title_pt-BR.png new file mode 100644 index 00000000000..d66fa829be1 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_exp_title_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_expbar_title_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_expbar_title_pt-BR.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_expbar_title_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_item_title_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_item_title_pt-BR.png new file mode 100644 index 00000000000..b9ea9400a64 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_item_title_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_stats_title_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_stats_title_pt-BR.png new file mode 100644 index 00000000000..bc9dffc2887 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_stats_stats_title_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_tabs_1_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_tabs_1_pt-BR.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_tabs_1_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_tabs_2_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_tabs_2_pt-BR.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_tabs_2_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/pt-BR/summary/summary_tabs_3_pt-BR.png b/public/images/ui/legacy/text_images/pt-BR/summary/summary_tabs_3_pt-BR.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/pt-BR/summary/summary_tabs_3_pt-BR.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_dexnb_label_overlay_shiny_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_dexnb_label_overlay_shiny_ro.png new file mode 100644 index 00000000000..bb2436738a8 Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_dexnb_label_overlay_shiny_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_dexnb_label_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_dexnb_label_ro.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_dexnb_label_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_moves_descriptions_title_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_moves_descriptions_title_ro.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_moves_descriptions_title_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_moves_effect_title_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_moves_effect_title_ro.png new file mode 100644 index 00000000000..fbbaac0b260 Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_moves_effect_title_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_moves_moves_title_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_moves_moves_title_ro.png new file mode 100644 index 00000000000..6bbb29c9c5f Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_moves_moves_title_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_moves_overlay_pp_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_moves_overlay_pp_ro.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_moves_overlay_pp_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_profile_ability_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_profile_ability_ro.png new file mode 100644 index 00000000000..a05c22b7d47 Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_profile_ability_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_profile_memo_title_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_profile_memo_title_ro.png new file mode 100644 index 00000000000..3d69c20e57f Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_profile_memo_title_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_profile_passive_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_profile_passive_ro.png new file mode 100644 index 00000000000..c026e87a215 Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_profile_passive_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_profile_profile_title_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_profile_profile_title_ro.png new file mode 100644 index 00000000000..4170dccf682 Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_profile_profile_title_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_stats_exp_title_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_stats_exp_title_ro.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_stats_exp_title_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_stats_expbar_title_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_stats_expbar_title_ro.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_stats_expbar_title_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_stats_item_title_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_stats_item_title_ro.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_stats_item_title_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_stats_stats_title_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_stats_stats_title_ro.png new file mode 100644 index 00000000000..f602a43c39d Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_stats_stats_title_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_tabs_1_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_tabs_1_ro.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_tabs_1_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_tabs_2_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_tabs_2_ro.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_tabs_2_ro.png differ diff --git a/public/images/ui/legacy/text_images/ro/summary/summary_tabs_3_ro.png b/public/images/ui/legacy/text_images/ro/summary/summary_tabs_3_ro.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/ro/summary/summary_tabs_3_ro.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_dexnb_label_overlay_shiny_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_dexnb_label_overlay_shiny_ru.png new file mode 100644 index 00000000000..1f8f6a1246e Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_dexnb_label_overlay_shiny_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_dexnb_label_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_dexnb_label_ru.png new file mode 100644 index 00000000000..2a2e66426cb Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_dexnb_label_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_moves_descriptions_title_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_moves_descriptions_title_ru.png new file mode 100644 index 00000000000..a435d6d845e Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_moves_descriptions_title_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_moves_effect_title_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_moves_effect_title_ru.png new file mode 100644 index 00000000000..8bd4b965247 Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_moves_effect_title_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_moves_moves_title_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_moves_moves_title_ru.png new file mode 100644 index 00000000000..94afd3226e8 Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_moves_moves_title_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_moves_overlay_pp_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_moves_overlay_pp_ru.png new file mode 100644 index 00000000000..4af1f833036 Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_moves_overlay_pp_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_profile_ability_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_profile_ability_ru.png new file mode 100644 index 00000000000..ddfcc6102dc Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_profile_ability_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_profile_memo_title_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_profile_memo_title_ru.png new file mode 100644 index 00000000000..743a2f36454 Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_profile_memo_title_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_profile_passive_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_profile_passive_ru.png new file mode 100644 index 00000000000..29179b6d75b Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_profile_passive_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_profile_profile_title_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_profile_profile_title_ru.png new file mode 100644 index 00000000000..77edb538634 Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_profile_profile_title_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_stats_exp_title_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_stats_exp_title_ru.png new file mode 100644 index 00000000000..e058eaa917e Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_stats_exp_title_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_stats_expbar_title_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_stats_expbar_title_ru.png new file mode 100644 index 00000000000..b885633d336 Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_stats_expbar_title_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_stats_item_title_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_stats_item_title_ru.png new file mode 100644 index 00000000000..95b01d062ab Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_stats_item_title_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_stats_stats_title_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_stats_stats_title_ru.png new file mode 100644 index 00000000000..0c1c5dc9445 Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_stats_stats_title_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_tabs_1_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_tabs_1_ru.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_tabs_1_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_tabs_2_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_tabs_2_ru.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_tabs_2_ru.png differ diff --git a/public/images/ui/legacy/text_images/ru/summary/summary_tabs_3_ru.png b/public/images/ui/legacy/text_images/ru/summary/summary_tabs_3_ru.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/ru/summary/summary_tabs_3_ru.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_dexnb_label_overlay_shiny_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_dexnb_label_overlay_shiny_tl.png new file mode 100644 index 00000000000..bb2436738a8 Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_dexnb_label_overlay_shiny_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_dexnb_label_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_dexnb_label_tl.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_dexnb_label_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_moves_descriptions_title_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_moves_descriptions_title_tl.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_moves_descriptions_title_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_moves_effect_title_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_moves_effect_title_tl.png new file mode 100644 index 00000000000..fbbaac0b260 Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_moves_effect_title_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_moves_moves_title_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_moves_moves_title_tl.png new file mode 100644 index 00000000000..6bbb29c9c5f Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_moves_moves_title_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_moves_overlay_pp_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_moves_overlay_pp_tl.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_moves_overlay_pp_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_profile_ability_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_profile_ability_tl.png new file mode 100644 index 00000000000..a05c22b7d47 Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_profile_ability_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_profile_memo_title_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_profile_memo_title_tl.png new file mode 100644 index 00000000000..3d69c20e57f Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_profile_memo_title_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_profile_passive_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_profile_passive_tl.png new file mode 100644 index 00000000000..c026e87a215 Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_profile_passive_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_profile_profile_title_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_profile_profile_title_tl.png new file mode 100644 index 00000000000..4170dccf682 Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_profile_profile_title_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_stats_exp_title_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_stats_exp_title_tl.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_stats_exp_title_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_stats_expbar_title.png b/public/images/ui/legacy/text_images/tl/summary/summary_stats_expbar_title.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_stats_expbar_title.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_stats_item_title_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_stats_item_title_tl.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_stats_item_title_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_stats_stats_title_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_stats_stats_title_tl.png new file mode 100644 index 00000000000..f602a43c39d Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_stats_stats_title_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_tabs_1_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_tabs_1_tl.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_tabs_1_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_tabs_2_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_tabs_2_tl.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_tabs_2_tl.png differ diff --git a/public/images/ui/legacy/text_images/tl/summary/summary_tabs_3_tl.png b/public/images/ui/legacy/text_images/tl/summary/summary_tabs_3_tl.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/tl/summary/summary_tabs_3_tl.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_dexnb_label_overlay_shiny_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_dexnb_label_overlay_shiny_tr.png new file mode 100644 index 00000000000..bb2436738a8 Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_dexnb_label_overlay_shiny_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_dexnb_label_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_dexnb_label_tr.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_dexnb_label_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_moves_descriptions_title_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_moves_descriptions_title_tr.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_moves_descriptions_title_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_moves_effect_title_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_moves_effect_title_tr.png new file mode 100644 index 00000000000..fbbaac0b260 Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_moves_effect_title_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_moves_moves_title_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_moves_moves_title_tr.png new file mode 100644 index 00000000000..6bbb29c9c5f Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_moves_moves_title_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_moves_overlay_pp_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_moves_overlay_pp_tr.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_moves_overlay_pp_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_profile_ability_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_profile_ability_tr.png new file mode 100644 index 00000000000..a05c22b7d47 Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_profile_ability_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_profile_memo_title_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_profile_memo_title_tr.png new file mode 100644 index 00000000000..3d69c20e57f Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_profile_memo_title_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_profile_passive_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_profile_passive_tr.png new file mode 100644 index 00000000000..c026e87a215 Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_profile_passive_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_profile_profile_title_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_profile_profile_title_tr.png new file mode 100644 index 00000000000..4170dccf682 Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_profile_profile_title_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_stats_exp_title_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_stats_exp_title_tr.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_stats_exp_title_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_stats_expbar_title_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_stats_expbar_title_tr.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_stats_expbar_title_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_stats_item_title_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_stats_item_title_tr.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_stats_item_title_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_stats_stats_title_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_stats_stats_title_tr.png new file mode 100644 index 00000000000..f602a43c39d Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_stats_stats_title_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_tabs_1_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_tabs_1_tr.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_tabs_1_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_tabs_2_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_tabs_2_tr.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_tabs_2_tr.png differ diff --git a/public/images/ui/legacy/text_images/tr/summary/summary_tabs_3_tr.png b/public/images/ui/legacy/text_images/tr/summary/summary_tabs_3_tr.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/tr/summary/summary_tabs_3_tr.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_dexnb_label_overlay_shiny_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_dexnb_label_overlay_shiny_zh-CN.png new file mode 100644 index 00000000000..bb2436738a8 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_dexnb_label_overlay_shiny_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_dexnb_label_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_dexnb_label_zh-CN.png new file mode 100644 index 00000000000..eab90a91c7f Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_dexnb_label_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_descriptions_title_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_descriptions_title_zh-CN.png new file mode 100644 index 00000000000..3d2b4d08376 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_descriptions_title_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_effect_title_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_effect_title_zh-CN.png new file mode 100644 index 00000000000..55fb0efd832 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_effect_title_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_moves_title_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_moves_title_zh-CN.png new file mode 100644 index 00000000000..d869ab4e311 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_moves_title_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_overlay_pp_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_overlay_pp_zh-CN.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_moves_overlay_pp_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_ability_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_ability_zh-CN.png new file mode 100644 index 00000000000..6600db26802 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_ability_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_memo_title_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_memo_title_zh-CN.png new file mode 100644 index 00000000000..14cdf099044 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_memo_title_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_passive_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_passive_zh-CN.png new file mode 100644 index 00000000000..66f56ff435e Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_passive_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_profile_title_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_profile_title_zh-CN.png new file mode 100644 index 00000000000..8d4f82df3b3 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_profile_profile_title_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_exp_title_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_exp_title_zh-CN.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_exp_title_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_expbar_title_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_expbar_title_zh-CN.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_expbar_title_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_item_title_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_item_title_zh-CN.png new file mode 100644 index 00000000000..5752b28288c Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_item_title_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_stats_title_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_stats_title_zh-CN.png new file mode 100644 index 00000000000..5531819ef66 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_stats_stats_title_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_tabs_1_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_tabs_1_zh-CN.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_tabs_1_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_tabs_2_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_tabs_2_zh-CN.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_tabs_2_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-CN/summary/summary_tabs_3_zh-CN.png b/public/images/ui/legacy/text_images/zh-CN/summary/summary_tabs_3_zh-CN.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-CN/summary/summary_tabs_3_zh-CN.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_dexnb_label_overlay_shiny_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_dexnb_label_overlay_shiny_zh-TW.png new file mode 100644 index 00000000000..bb2436738a8 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_dexnb_label_overlay_shiny_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_dexnb_label_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_dexnb_label_zh-TW.png new file mode 100644 index 00000000000..eab90a91c7f Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_dexnb_label_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_descriptions_title_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_descriptions_title_zh-TW.png new file mode 100644 index 00000000000..3d2b4d08376 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_descriptions_title_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_effect_title_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_effect_title_zh-TW.png new file mode 100644 index 00000000000..55fb0efd832 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_effect_title_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_moves_title_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_moves_title_zh-TW.png new file mode 100644 index 00000000000..d869ab4e311 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_moves_title_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_overlay_pp_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_overlay_pp_zh-TW.png new file mode 100644 index 00000000000..9babffc0429 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_moves_overlay_pp_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_ability_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_ability_zh-TW.png new file mode 100644 index 00000000000..6600db26802 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_ability_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_memo_title_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_memo_title_zh-TW.png new file mode 100644 index 00000000000..14cdf099044 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_memo_title_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_passive_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_passive_zh-TW.png new file mode 100644 index 00000000000..66f56ff435e Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_passive_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_profile_title_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_profile_title_zh-TW.png new file mode 100644 index 00000000000..8d4f82df3b3 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_profile_profile_title_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_exp_title_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_exp_title_zh-TW.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_exp_title_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_expbar_title_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_expbar_title_zh-TW.png new file mode 100644 index 00000000000..e9dfb10e5d6 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_expbar_title_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_item_title_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_item_title_zh-TW.png new file mode 100644 index 00000000000..5752b28288c Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_item_title_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_stats_title_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_stats_title_zh-TW.png new file mode 100644 index 00000000000..5531819ef66 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_stats_stats_title_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_tabs_1_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_tabs_1_zh-TW.png new file mode 100644 index 00000000000..379768ea310 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_tabs_1_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_tabs_2_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_tabs_2_zh-TW.png new file mode 100644 index 00000000000..2a04879b32b Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_tabs_2_zh-TW.png differ diff --git a/public/images/ui/legacy/text_images/zh-TW/summary/summary_tabs_3_zh-TW.png b/public/images/ui/legacy/text_images/zh-TW/summary/summary_tabs_3_zh-TW.png new file mode 100644 index 00000000000..ef65774f744 Binary files /dev/null and b/public/images/ui/legacy/text_images/zh-TW/summary/summary_tabs_3_zh-TW.png differ diff --git a/public/images/ui/pokedex_summary_bg.png b/public/images/ui/pokedex_summary_bg.png index bb55127edf2..423bc7528fd 100644 Binary files a/public/images/ui/pokedex_summary_bg.png and b/public/images/ui/pokedex_summary_bg.png differ diff --git a/public/images/ui/starter_select_bg.png b/public/images/ui/starter_select_bg.png index b11cd12a5e4..14e90dd0f85 100644 Binary files a/public/images/ui/starter_select_bg.png and b/public/images/ui/starter_select_bg.png differ diff --git a/public/images/ui/summary_bg.png b/public/images/ui/summary_bg.png index ebfe87b78b2..4bdb6d0db22 100644 Binary files a/public/images/ui/summary_bg.png and b/public/images/ui/summary_bg.png differ diff --git a/public/images/ui/summary_moves.png b/public/images/ui/summary_moves.png index 618d91934f2..7f53809d052 100644 Binary files a/public/images/ui/summary_moves.png and b/public/images/ui/summary_moves.png differ diff --git a/public/images/ui/summary_moves_effect.png b/public/images/ui/summary_moves_effect.png index 7993cd0ad57..f8ead3c5263 100644 Binary files a/public/images/ui/summary_moves_effect.png and b/public/images/ui/summary_moves_effect.png differ diff --git a/public/images/ui/summary_overlay_shiny.png b/public/images/ui/summary_overlay_shiny.png deleted file mode 100644 index 956f9fb93f3..00000000000 Binary files a/public/images/ui/summary_overlay_shiny.png and /dev/null differ diff --git a/public/images/ui/summary_profile.png b/public/images/ui/summary_profile.png index 2c0c93af6b4..6362148f9d9 100644 Binary files a/public/images/ui/summary_profile.png and b/public/images/ui/summary_profile.png differ diff --git a/public/images/ui/summary_profile_ability.png b/public/images/ui/summary_profile_ability.png deleted file mode 100644 index f839a6249f8..00000000000 Binary files a/public/images/ui/summary_profile_ability.png and /dev/null differ diff --git a/public/images/ui/summary_profile_passive.png b/public/images/ui/summary_profile_passive.png deleted file mode 100644 index 1ff9ad8e09a..00000000000 Binary files a/public/images/ui/summary_profile_passive.png and /dev/null differ diff --git a/public/images/ui/summary_stats.png b/public/images/ui/summary_stats.png index d808be92fd1..bcfc55fb6aa 100644 Binary files a/public/images/ui/summary_stats.png and b/public/images/ui/summary_stats.png differ diff --git a/public/images/ui/summary_tabs_2.png b/public/images/ui/summary_tabs_2.png deleted file mode 100644 index 250c3ce7960..00000000000 Binary files a/public/images/ui/summary_tabs_2.png and /dev/null differ diff --git a/public/images/ui/summary_tabs_3.png b/public/images/ui/summary_tabs_3.png deleted file mode 100644 index 1af80fa5c0d..00000000000 Binary files a/public/images/ui/summary_tabs_3.png and /dev/null differ diff --git a/public/images/ui/text_images/ca/summary/summary_dexnb_label_ca.png b/public/images/ui/text_images/ca/summary/summary_dexnb_label_ca.png new file mode 100644 index 00000000000..5477e3385a8 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_dexnb_label_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_dexnb_label_overlay_shiny_ca.png b/public/images/ui/text_images/ca/summary/summary_dexnb_label_overlay_shiny_ca.png new file mode 100644 index 00000000000..54f0c3799a0 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_dexnb_label_overlay_shiny_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_moves_descriptions_title_ca.png b/public/images/ui/text_images/ca/summary/summary_moves_descriptions_title_ca.png new file mode 100644 index 00000000000..a37aad953cc Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_moves_descriptions_title_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_moves_effect_title_ca.png b/public/images/ui/text_images/ca/summary/summary_moves_effect_title_ca.png new file mode 100644 index 00000000000..ca66436eca6 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_moves_effect_title_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_moves_moves_title_ca.png b/public/images/ui/text_images/ca/summary/summary_moves_moves_title_ca.png new file mode 100644 index 00000000000..71a6889da53 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_moves_moves_title_ca.png differ diff --git a/public/images/ui/summary_moves_overlay_pp.png b/public/images/ui/text_images/ca/summary/summary_moves_overlay_pp_ca.png similarity index 100% rename from public/images/ui/summary_moves_overlay_pp.png rename to public/images/ui/text_images/ca/summary/summary_moves_overlay_pp_ca.png diff --git a/public/images/ui/text_images/ca/summary/summary_profile_ability_ca.png b/public/images/ui/text_images/ca/summary/summary_profile_ability_ca.png new file mode 100644 index 00000000000..2d9e8ac317d Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_profile_ability_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_profile_memo_title_ca.png b/public/images/ui/text_images/ca/summary/summary_profile_memo_title_ca.png new file mode 100644 index 00000000000..b7ef7c91fc5 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_profile_memo_title_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_profile_passive_ca.png b/public/images/ui/text_images/ca/summary/summary_profile_passive_ca.png new file mode 100644 index 00000000000..a072b663d25 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_profile_passive_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_profile_profile_title_ca.png b/public/images/ui/text_images/ca/summary/summary_profile_profile_title_ca.png new file mode 100644 index 00000000000..a5ed0e3e169 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_profile_profile_title_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_stats_exp_title_ca.png b/public/images/ui/text_images/ca/summary/summary_stats_exp_title_ca.png new file mode 100644 index 00000000000..e7ac7268b54 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_stats_exp_title_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_stats_expbar_title_ca.png b/public/images/ui/text_images/ca/summary/summary_stats_expbar_title_ca.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_stats_expbar_title_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_stats_item_title_ca.png b/public/images/ui/text_images/ca/summary/summary_stats_item_title_ca.png new file mode 100644 index 00000000000..c13189fc816 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_stats_item_title_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_stats_stats_title_ca.png b/public/images/ui/text_images/ca/summary/summary_stats_stats_title_ca.png new file mode 100644 index 00000000000..426848af866 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_stats_stats_title_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_tabs_1_ca.png b/public/images/ui/text_images/ca/summary/summary_tabs_1_ca.png new file mode 100644 index 00000000000..1e1ad63672e Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_tabs_1_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_tabs_2_ca.png b/public/images/ui/text_images/ca/summary/summary_tabs_2_ca.png new file mode 100644 index 00000000000..bf794e82d20 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_tabs_2_ca.png differ diff --git a/public/images/ui/text_images/ca/summary/summary_tabs_3_ca.png b/public/images/ui/text_images/ca/summary/summary_tabs_3_ca.png new file mode 100644 index 00000000000..6a0109997b2 Binary files /dev/null and b/public/images/ui/text_images/ca/summary/summary_tabs_3_ca.png differ diff --git a/public/images/ui/text_images/da/summary/summary_dexnb_label_da.png b/public/images/ui/text_images/da/summary/summary_dexnb_label_da.png new file mode 100644 index 00000000000..ef081f493f3 Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_dexnb_label_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_dexnb_label_overlay_shiny_da.png b/public/images/ui/text_images/da/summary/summary_dexnb_label_overlay_shiny_da.png new file mode 100644 index 00000000000..2c66a714e0c Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_dexnb_label_overlay_shiny_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_moves_descriptions_title_da.png b/public/images/ui/text_images/da/summary/summary_moves_descriptions_title_da.png new file mode 100644 index 00000000000..79b16227bfe Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_moves_descriptions_title_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_moves_effect_title_da.png b/public/images/ui/text_images/da/summary/summary_moves_effect_title_da.png new file mode 100644 index 00000000000..f2ac04e62c4 Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_moves_effect_title_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_moves_moves_title_da.png b/public/images/ui/text_images/da/summary/summary_moves_moves_title_da.png new file mode 100644 index 00000000000..f1732e3e2c0 Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_moves_moves_title_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_moves_overlay_pp_da.png b/public/images/ui/text_images/da/summary/summary_moves_overlay_pp_da.png new file mode 100644 index 00000000000..04430665f8f Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_moves_overlay_pp_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_profile_ability_da.png b/public/images/ui/text_images/da/summary/summary_profile_ability_da.png new file mode 100644 index 00000000000..206b65c6cdd Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_profile_ability_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_profile_memo_title_da.png b/public/images/ui/text_images/da/summary/summary_profile_memo_title_da.png new file mode 100644 index 00000000000..48886d25e39 Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_profile_memo_title_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_profile_passive_da.png b/public/images/ui/text_images/da/summary/summary_profile_passive_da.png new file mode 100644 index 00000000000..681ae3f1b5e Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_profile_passive_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_profile_profile_title_da.png b/public/images/ui/text_images/da/summary/summary_profile_profile_title_da.png new file mode 100644 index 00000000000..83b8a1d5e99 Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_profile_profile_title_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_stats_exp_title_da.png b/public/images/ui/text_images/da/summary/summary_stats_exp_title_da.png new file mode 100644 index 00000000000..feae0c9cb90 Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_stats_exp_title_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_stats_expbar_title_da.png b/public/images/ui/text_images/da/summary/summary_stats_expbar_title_da.png new file mode 100644 index 00000000000..566dd844aa6 Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_stats_expbar_title_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_stats_item_title_da.png b/public/images/ui/text_images/da/summary/summary_stats_item_title_da.png new file mode 100644 index 00000000000..2cbce6c3dcf Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_stats_item_title_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_stats_stats_title_da.png b/public/images/ui/text_images/da/summary/summary_stats_stats_title_da.png new file mode 100644 index 00000000000..ff97416c7ed Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_stats_stats_title_da.png differ diff --git a/public/images/ui/summary_tabs_1.png b/public/images/ui/text_images/da/summary/summary_tabs_1_da.png similarity index 100% rename from public/images/ui/summary_tabs_1.png rename to public/images/ui/text_images/da/summary/summary_tabs_1_da.png diff --git a/public/images/ui/text_images/da/summary/summary_tabs_2_da.png b/public/images/ui/text_images/da/summary/summary_tabs_2_da.png new file mode 100644 index 00000000000..e8dd00bc7e0 Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_tabs_2_da.png differ diff --git a/public/images/ui/text_images/da/summary/summary_tabs_3_da.png b/public/images/ui/text_images/da/summary/summary_tabs_3_da.png new file mode 100644 index 00000000000..a274f79e4e2 Binary files /dev/null and b/public/images/ui/text_images/da/summary/summary_tabs_3_da.png differ diff --git a/public/images/ui/text_images/de/summary/summary_dexnb_label_de.png b/public/images/ui/text_images/de/summary/summary_dexnb_label_de.png new file mode 100644 index 00000000000..ef081f493f3 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_dexnb_label_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_dexnb_label_overlay_shiny_de.png b/public/images/ui/text_images/de/summary/summary_dexnb_label_overlay_shiny_de.png new file mode 100644 index 00000000000..2c66a714e0c Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_dexnb_label_overlay_shiny_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_moves_descriptions_title_de.png b/public/images/ui/text_images/de/summary/summary_moves_descriptions_title_de.png new file mode 100644 index 00000000000..ea4827c081d Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_moves_descriptions_title_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_moves_effect_title_de.png b/public/images/ui/text_images/de/summary/summary_moves_effect_title_de.png new file mode 100644 index 00000000000..951e9281839 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_moves_effect_title_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_moves_moves_title_de.png b/public/images/ui/text_images/de/summary/summary_moves_moves_title_de.png new file mode 100644 index 00000000000..d5e28d3dfe7 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_moves_moves_title_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_moves_overlay_pp_de.png b/public/images/ui/text_images/de/summary/summary_moves_overlay_pp_de.png new file mode 100644 index 00000000000..5db3861fbc9 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_moves_overlay_pp_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_profile_ability_de.png b/public/images/ui/text_images/de/summary/summary_profile_ability_de.png new file mode 100644 index 00000000000..2b6bd055555 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_profile_ability_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_profile_memo_title_de.png b/public/images/ui/text_images/de/summary/summary_profile_memo_title_de.png new file mode 100644 index 00000000000..089668218fa Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_profile_memo_title_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_profile_passive_de.png b/public/images/ui/text_images/de/summary/summary_profile_passive_de.png new file mode 100644 index 00000000000..681ae3f1b5e Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_profile_passive_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_profile_profile_title_de.png b/public/images/ui/text_images/de/summary/summary_profile_profile_title_de.png new file mode 100644 index 00000000000..83b8a1d5e99 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_profile_profile_title_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_stats_exp_title_de.png b/public/images/ui/text_images/de/summary/summary_stats_exp_title_de.png new file mode 100644 index 00000000000..fa702b4c223 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_stats_exp_title_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_stats_expbar_title_de.png b/public/images/ui/text_images/de/summary/summary_stats_expbar_title_de.png new file mode 100644 index 00000000000..566dd844aa6 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_stats_expbar_title_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_stats_item_title_de.png b/public/images/ui/text_images/de/summary/summary_stats_item_title_de.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_stats_item_title_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_stats_stats_title_de.png b/public/images/ui/text_images/de/summary/summary_stats_stats_title_de.png new file mode 100644 index 00000000000..87438a5bd4f Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_stats_stats_title_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_tabs_1_de.png b/public/images/ui/text_images/de/summary/summary_tabs_1_de.png new file mode 100644 index 00000000000..9c3e6c795b4 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_tabs_1_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_tabs_2_de.png b/public/images/ui/text_images/de/summary/summary_tabs_2_de.png new file mode 100644 index 00000000000..750c407b075 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_tabs_2_de.png differ diff --git a/public/images/ui/text_images/de/summary/summary_tabs_3_de.png b/public/images/ui/text_images/de/summary/summary_tabs_3_de.png new file mode 100644 index 00000000000..297df98c111 Binary files /dev/null and b/public/images/ui/text_images/de/summary/summary_tabs_3_de.png differ diff --git a/public/images/ui/text_images/en/summary/summary_dexnb_label.png b/public/images/ui/text_images/en/summary/summary_dexnb_label.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_dexnb_label.png differ diff --git a/public/images/ui/text_images/en/summary/summary_dexnb_label_overlay_shiny.png b/public/images/ui/text_images/en/summary/summary_dexnb_label_overlay_shiny.png new file mode 100644 index 00000000000..f35e327c29a Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_dexnb_label_overlay_shiny.png differ diff --git a/public/images/ui/text_images/en/summary/summary_moves_descriptions_title.png b/public/images/ui/text_images/en/summary/summary_moves_descriptions_title.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_moves_descriptions_title.png differ diff --git a/public/images/ui/text_images/en/summary/summary_moves_effect_title.png b/public/images/ui/text_images/en/summary/summary_moves_effect_title.png new file mode 100644 index 00000000000..fbbaac0b260 Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_moves_effect_title.png differ diff --git a/public/images/ui/text_images/en/summary/summary_moves_moves_title.png b/public/images/ui/text_images/en/summary/summary_moves_moves_title.png new file mode 100644 index 00000000000..6bbb29c9c5f Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_moves_moves_title.png differ diff --git a/public/images/ui/text_images/en/summary/summary_moves_overlay_pp.png b/public/images/ui/text_images/en/summary/summary_moves_overlay_pp.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_moves_overlay_pp.png differ diff --git a/public/images/ui/text_images/en/summary/summary_profile_ability.png b/public/images/ui/text_images/en/summary/summary_profile_ability.png new file mode 100644 index 00000000000..a05c22b7d47 Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_profile_ability.png differ diff --git a/public/images/ui/text_images/en/summary/summary_profile_memo_title.png b/public/images/ui/text_images/en/summary/summary_profile_memo_title.png new file mode 100644 index 00000000000..3d69c20e57f Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_profile_memo_title.png differ diff --git a/public/images/ui/text_images/en/summary/summary_profile_passive.png b/public/images/ui/text_images/en/summary/summary_profile_passive.png new file mode 100644 index 00000000000..c026e87a215 Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_profile_passive.png differ diff --git a/public/images/ui/text_images/en/summary/summary_profile_profile_title.png b/public/images/ui/text_images/en/summary/summary_profile_profile_title.png new file mode 100644 index 00000000000..4170dccf682 Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_profile_profile_title.png differ diff --git a/public/images/ui/text_images/en/summary/summary_stats_exp_title.png b/public/images/ui/text_images/en/summary/summary_stats_exp_title.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_stats_exp_title.png differ diff --git a/public/images/ui/text_images/en/summary/summary_stats_expbar_title.png b/public/images/ui/text_images/en/summary/summary_stats_expbar_title.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_stats_expbar_title.png differ diff --git a/public/images/ui/text_images/en/summary/summary_stats_item_title.png b/public/images/ui/text_images/en/summary/summary_stats_item_title.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_stats_item_title.png differ diff --git a/public/images/ui/text_images/en/summary/summary_stats_stats_title.png b/public/images/ui/text_images/en/summary/summary_stats_stats_title.png new file mode 100644 index 00000000000..f602a43c39d Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_stats_stats_title.png differ diff --git a/public/images/ui/text_images/en/summary/summary_tabs_1.png b/public/images/ui/text_images/en/summary/summary_tabs_1.png new file mode 100644 index 00000000000..750c407b075 Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_tabs_1.png differ diff --git a/public/images/ui/text_images/en/summary/summary_tabs_2.png b/public/images/ui/text_images/en/summary/summary_tabs_2.png new file mode 100644 index 00000000000..50c1db1f34c Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_tabs_2.png differ diff --git a/public/images/ui/text_images/en/summary/summary_tabs_3.png b/public/images/ui/text_images/en/summary/summary_tabs_3.png new file mode 100644 index 00000000000..24676712fb9 Binary files /dev/null and b/public/images/ui/text_images/en/summary/summary_tabs_3.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_dexnb_label_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_dexnb_label_es-ES.png new file mode 100644 index 00000000000..5477e3385a8 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_dexnb_label_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_dexnb_label_overlay_shiny_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_dexnb_label_overlay_shiny_es-ES.png new file mode 100644 index 00000000000..54f0c3799a0 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_dexnb_label_overlay_shiny_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_moves_descriptions_title_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_moves_descriptions_title_es-ES.png new file mode 100644 index 00000000000..3a4e3c7c375 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_moves_descriptions_title_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_moves_effect_title_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_moves_effect_title_es-ES.png new file mode 100644 index 00000000000..cf8d1309848 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_moves_effect_title_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_moves_moves_title_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_moves_moves_title_es-ES.png new file mode 100644 index 00000000000..a601ae79e4f Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_moves_moves_title_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_moves_overlay_pp_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_moves_overlay_pp_es-ES.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_moves_overlay_pp_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_profile_ability_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_profile_ability_es-ES.png new file mode 100644 index 00000000000..71bffe95cfe Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_profile_ability_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_profile_memo_title_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_profile_memo_title_es-ES.png new file mode 100644 index 00000000000..b7ef7c91fc5 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_profile_memo_title_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_profile_passive_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_profile_passive_es-ES.png new file mode 100644 index 00000000000..a50e3cacf58 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_profile_passive_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_profile_profile_title_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_profile_profile_title_es-ES.png new file mode 100644 index 00000000000..a5ed0e3e169 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_profile_profile_title_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_stats_exp_title_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_stats_exp_title_es-ES.png new file mode 100644 index 00000000000..7c8a80f0627 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_stats_exp_title_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_stats_expbar_title_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_stats_expbar_title_es-ES.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_stats_expbar_title_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_stats_item_title_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_stats_item_title_es-ES.png new file mode 100644 index 00000000000..9236aaa1ff8 Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_stats_item_title_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_stats_stats_title_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_stats_stats_title_es-ES.png new file mode 100644 index 00000000000..5b59c12984f Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_stats_stats_title_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_tabs_1_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_tabs_1_es-ES.png new file mode 100644 index 00000000000..99f187c396f Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_tabs_1_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_tabs_2_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_tabs_2_es-ES.png new file mode 100644 index 00000000000..c841de2c12c Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_tabs_2_es-ES.png differ diff --git a/public/images/ui/text_images/es-ES/summary/summary_tabs_3_es-ES.png b/public/images/ui/text_images/es-ES/summary/summary_tabs_3_es-ES.png new file mode 100644 index 00000000000..805fec323dd Binary files /dev/null and b/public/images/ui/text_images/es-ES/summary/summary_tabs_3_es-ES.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_dexnb_label_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_dexnb_label_es-MX.png new file mode 100644 index 00000000000..5477e3385a8 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_dexnb_label_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_dexnb_label_overlay_shiny_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_dexnb_label_overlay_shiny_es-MX.png new file mode 100644 index 00000000000..54f0c3799a0 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_dexnb_label_overlay_shiny_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_moves_descriptions_title_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_moves_descriptions_title_es-MX.png new file mode 100644 index 00000000000..3a4e3c7c375 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_moves_descriptions_title_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_moves_effect_title_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_moves_effect_title_es-MX.png new file mode 100644 index 00000000000..cf8d1309848 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_moves_effect_title_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_moves_moves_title_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_moves_moves_title_es-MX.png new file mode 100644 index 00000000000..a601ae79e4f Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_moves_moves_title_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_moves_overlay_pp_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_moves_overlay_pp_es-MX.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_moves_overlay_pp_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_profile_ability_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_profile_ability_es-MX.png new file mode 100644 index 00000000000..71bffe95cfe Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_profile_ability_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_profile_memo_title_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_profile_memo_title_es-MX.png new file mode 100644 index 00000000000..b7ef7c91fc5 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_profile_memo_title_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_profile_passive_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_profile_passive_es-MX.png new file mode 100644 index 00000000000..a50e3cacf58 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_profile_passive_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_profile_profile_title_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_profile_profile_title_es-MX.png new file mode 100644 index 00000000000..a5ed0e3e169 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_profile_profile_title_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_stats_exp_title_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_stats_exp_title_es-MX.png new file mode 100644 index 00000000000..7c8a80f0627 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_stats_exp_title_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_stats_expbar_title_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_stats_expbar_title_es-MX.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_stats_expbar_title_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_stats_item_title_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_stats_item_title_es-MX.png new file mode 100644 index 00000000000..9236aaa1ff8 Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_stats_item_title_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_stats_stats_title_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_stats_stats_title_es-MX.png new file mode 100644 index 00000000000..5b59c12984f Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_stats_stats_title_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_tabs_1_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_tabs_1_es-MX.png new file mode 100644 index 00000000000..99f187c396f Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_tabs_1_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_tabs_2_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_tabs_2_es-MX.png new file mode 100644 index 00000000000..c841de2c12c Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_tabs_2_es-MX.png differ diff --git a/public/images/ui/text_images/es-MX/summary/summary_tabs_3_es-MX.png b/public/images/ui/text_images/es-MX/summary/summary_tabs_3_es-MX.png new file mode 100644 index 00000000000..805fec323dd Binary files /dev/null and b/public/images/ui/text_images/es-MX/summary/summary_tabs_3_es-MX.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_dexnb_label_fr.png b/public/images/ui/text_images/fr/summary/summary_dexnb_label_fr.png new file mode 100644 index 00000000000..5477e3385a8 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_dexnb_label_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_dexnb_label_overlay_shiny_fr.png b/public/images/ui/text_images/fr/summary/summary_dexnb_label_overlay_shiny_fr.png new file mode 100644 index 00000000000..54f0c3799a0 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_dexnb_label_overlay_shiny_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_moves_descriptions_title_fr.png b/public/images/ui/text_images/fr/summary/summary_moves_descriptions_title_fr.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_moves_descriptions_title_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_moves_effect_title_fr.png b/public/images/ui/text_images/fr/summary/summary_moves_effect_title_fr.png new file mode 100644 index 00000000000..49f4e11096a Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_moves_effect_title_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_moves_moves_title_fr.png b/public/images/ui/text_images/fr/summary/summary_moves_moves_title_fr.png new file mode 100644 index 00000000000..1fd7d72c307 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_moves_moves_title_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_moves_overlay_pp_fr.png b/public/images/ui/text_images/fr/summary/summary_moves_overlay_pp_fr.png new file mode 100644 index 00000000000..8285fb09c45 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_moves_overlay_pp_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_profile_ability_fr.png b/public/images/ui/text_images/fr/summary/summary_profile_ability_fr.png new file mode 100644 index 00000000000..3354b40adfe Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_profile_ability_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_profile_memo_title_fr.png b/public/images/ui/text_images/fr/summary/summary_profile_memo_title_fr.png new file mode 100644 index 00000000000..54c6beb4428 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_profile_memo_title_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_profile_passive_fr.png b/public/images/ui/text_images/fr/summary/summary_profile_passive_fr.png new file mode 100644 index 00000000000..f5d2c98a21c Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_profile_passive_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_profile_profile_title_fr.png b/public/images/ui/text_images/fr/summary/summary_profile_profile_title_fr.png new file mode 100644 index 00000000000..bccba2d87df Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_profile_profile_title_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_stats_exp_title_fr.png b/public/images/ui/text_images/fr/summary/summary_stats_exp_title_fr.png new file mode 100644 index 00000000000..32d41d44be4 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_stats_exp_title_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_stats_expbar_title_fr.png b/public/images/ui/text_images/fr/summary/summary_stats_expbar_title_fr.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_stats_expbar_title_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_stats_item_title_fr.png b/public/images/ui/text_images/fr/summary/summary_stats_item_title_fr.png new file mode 100644 index 00000000000..45c10e8c907 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_stats_item_title_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_stats_stats_title_fr.png b/public/images/ui/text_images/fr/summary/summary_stats_stats_title_fr.png new file mode 100644 index 00000000000..63fe6a694af Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_stats_stats_title_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_tabs_1_fr.png b/public/images/ui/text_images/fr/summary/summary_tabs_1_fr.png new file mode 100644 index 00000000000..dd918e773e9 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_tabs_1_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_tabs_2_fr.png b/public/images/ui/text_images/fr/summary/summary_tabs_2_fr.png new file mode 100644 index 00000000000..6e53366bec3 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_tabs_2_fr.png differ diff --git a/public/images/ui/text_images/fr/summary/summary_tabs_3_fr.png b/public/images/ui/text_images/fr/summary/summary_tabs_3_fr.png new file mode 100644 index 00000000000..d4c353084a3 Binary files /dev/null and b/public/images/ui/text_images/fr/summary/summary_tabs_3_fr.png differ diff --git a/public/images/ui/text_images/it/summary/summary_dexnb_label_it.png b/public/images/ui/text_images/it/summary/summary_dexnb_label_it.png new file mode 100644 index 00000000000..5477e3385a8 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_dexnb_label_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_dexnb_label_overlay_shiny_it.png b/public/images/ui/text_images/it/summary/summary_dexnb_label_overlay_shiny_it.png new file mode 100644 index 00000000000..54f0c3799a0 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_dexnb_label_overlay_shiny_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_moves_descriptions_title_it.png b/public/images/ui/text_images/it/summary/summary_moves_descriptions_title_it.png new file mode 100644 index 00000000000..e0bf21396e5 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_moves_descriptions_title_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_moves_effect_title_it.png b/public/images/ui/text_images/it/summary/summary_moves_effect_title_it.png new file mode 100644 index 00000000000..99f9dfeb2c3 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_moves_effect_title_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_moves_moves_title_it.png b/public/images/ui/text_images/it/summary/summary_moves_moves_title_it.png new file mode 100644 index 00000000000..e56e3f4b336 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_moves_moves_title_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_moves_overlay_pp_it.png b/public/images/ui/text_images/it/summary/summary_moves_overlay_pp_it.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_moves_overlay_pp_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_profile_ability_it.png b/public/images/ui/text_images/it/summary/summary_profile_ability_it.png new file mode 100644 index 00000000000..bb915da37ee Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_profile_ability_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_profile_memo_title_it.png b/public/images/ui/text_images/it/summary/summary_profile_memo_title_it.png new file mode 100644 index 00000000000..0c81cd56f06 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_profile_memo_title_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_profile_passive_it.png b/public/images/ui/text_images/it/summary/summary_profile_passive_it.png new file mode 100644 index 00000000000..a072b663d25 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_profile_passive_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_profile_profile_title_it.png b/public/images/ui/text_images/it/summary/summary_profile_profile_title_it.png new file mode 100644 index 00000000000..169b0a7b8e7 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_profile_profile_title_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_stats_exp_title_it.png b/public/images/ui/text_images/it/summary/summary_stats_exp_title_it.png new file mode 100644 index 00000000000..a3a1aa4c402 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_stats_exp_title_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_stats_expbar_title_it.png b/public/images/ui/text_images/it/summary/summary_stats_expbar_title_it.png new file mode 100644 index 00000000000..d6cd930c1c2 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_stats_expbar_title_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_stats_item_title_it.png b/public/images/ui/text_images/it/summary/summary_stats_item_title_it.png new file mode 100644 index 00000000000..a93695a48c8 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_stats_item_title_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_stats_stats_title_it.png b/public/images/ui/text_images/it/summary/summary_stats_stats_title_it.png new file mode 100644 index 00000000000..998db7fc7e3 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_stats_stats_title_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_tabs_1_it.png b/public/images/ui/text_images/it/summary/summary_tabs_1_it.png new file mode 100644 index 00000000000..933a381dd50 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_tabs_1_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_tabs_2_it.png b/public/images/ui/text_images/it/summary/summary_tabs_2_it.png new file mode 100644 index 00000000000..07c73fbdb90 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_tabs_2_it.png differ diff --git a/public/images/ui/text_images/it/summary/summary_tabs_3_it.png b/public/images/ui/text_images/it/summary/summary_tabs_3_it.png new file mode 100644 index 00000000000..57e8b176be1 Binary files /dev/null and b/public/images/ui/text_images/it/summary/summary_tabs_3_it.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_dexnb_label_ja.png b/public/images/ui/text_images/ja/summary/summary_dexnb_label_ja.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_dexnb_label_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_dexnb_label_overlay_shiny_ja.png b/public/images/ui/text_images/ja/summary/summary_dexnb_label_overlay_shiny_ja.png new file mode 100644 index 00000000000..f35e327c29a Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_dexnb_label_overlay_shiny_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_moves_descriptions_title_ja.png b/public/images/ui/text_images/ja/summary/summary_moves_descriptions_title_ja.png new file mode 100644 index 00000000000..d844e844244 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_moves_descriptions_title_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_moves_effect_title_ja.png b/public/images/ui/text_images/ja/summary/summary_moves_effect_title_ja.png new file mode 100644 index 00000000000..a75452f1299 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_moves_effect_title_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_moves_moves_title_ja.png b/public/images/ui/text_images/ja/summary/summary_moves_moves_title_ja.png new file mode 100644 index 00000000000..6492c3ecf7c Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_moves_moves_title_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_moves_overlay_pp_ja.png b/public/images/ui/text_images/ja/summary/summary_moves_overlay_pp_ja.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_moves_overlay_pp_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_profile_ability_ja.png b/public/images/ui/text_images/ja/summary/summary_profile_ability_ja.png new file mode 100644 index 00000000000..6c82a863a69 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_profile_ability_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_profile_memo_title_ja.png b/public/images/ui/text_images/ja/summary/summary_profile_memo_title_ja.png new file mode 100644 index 00000000000..3f5a4536817 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_profile_memo_title_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_profile_passive_ja.png b/public/images/ui/text_images/ja/summary/summary_profile_passive_ja.png new file mode 100644 index 00000000000..3bfed88c7da Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_profile_passive_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_profile_profile_title_ja.png b/public/images/ui/text_images/ja/summary/summary_profile_profile_title_ja.png new file mode 100644 index 00000000000..a05cba49247 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_profile_profile_title_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_stats_exp_title_ja.png b/public/images/ui/text_images/ja/summary/summary_stats_exp_title_ja.png new file mode 100644 index 00000000000..0bc237a7e6b Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_stats_exp_title_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_stats_expbar_title_ja.png b/public/images/ui/text_images/ja/summary/summary_stats_expbar_title_ja.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_stats_expbar_title_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_stats_item_title_ja.png b/public/images/ui/text_images/ja/summary/summary_stats_item_title_ja.png new file mode 100644 index 00000000000..114b4d7fd3f Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_stats_item_title_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_stats_stats_title_ja.png b/public/images/ui/text_images/ja/summary/summary_stats_stats_title_ja.png new file mode 100644 index 00000000000..c9f2e28fb07 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_stats_stats_title_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_tabs_1_ja.png b/public/images/ui/text_images/ja/summary/summary_tabs_1_ja.png new file mode 100644 index 00000000000..90f454dae75 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_tabs_1_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_tabs_2_ja.png b/public/images/ui/text_images/ja/summary/summary_tabs_2_ja.png new file mode 100644 index 00000000000..006c33f23b1 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_tabs_2_ja.png differ diff --git a/public/images/ui/text_images/ja/summary/summary_tabs_3_ja.png b/public/images/ui/text_images/ja/summary/summary_tabs_3_ja.png new file mode 100644 index 00000000000..3306d0aba62 Binary files /dev/null and b/public/images/ui/text_images/ja/summary/summary_tabs_3_ja.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_dexnb_label_ko.png b/public/images/ui/text_images/ko/summary/summary_dexnb_label_ko.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_dexnb_label_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_dexnb_label_overlay_shiny_ko.png b/public/images/ui/text_images/ko/summary/summary_dexnb_label_overlay_shiny_ko.png new file mode 100644 index 00000000000..f35e327c29a Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_dexnb_label_overlay_shiny_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_moves_descriptions_title_ko.png b/public/images/ui/text_images/ko/summary/summary_moves_descriptions_title_ko.png new file mode 100644 index 00000000000..350bd607aed Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_moves_descriptions_title_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_moves_effect_title_ko.png b/public/images/ui/text_images/ko/summary/summary_moves_effect_title_ko.png new file mode 100644 index 00000000000..f90ac18fc4e Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_moves_effect_title_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_moves_moves_title_ko.png b/public/images/ui/text_images/ko/summary/summary_moves_moves_title_ko.png new file mode 100644 index 00000000000..d020d8a77cb Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_moves_moves_title_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_moves_overlay_pp_ko.png b/public/images/ui/text_images/ko/summary/summary_moves_overlay_pp_ko.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_moves_overlay_pp_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_profile_ability_ko.png b/public/images/ui/text_images/ko/summary/summary_profile_ability_ko.png new file mode 100644 index 00000000000..cdeafaf486e Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_profile_ability_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_profile_memo_title_ko.png b/public/images/ui/text_images/ko/summary/summary_profile_memo_title_ko.png new file mode 100644 index 00000000000..7af960fe1df Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_profile_memo_title_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_profile_passive_ko.png b/public/images/ui/text_images/ko/summary/summary_profile_passive_ko.png new file mode 100644 index 00000000000..34a13ffe836 Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_profile_passive_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_profile_profile_title_ko.png b/public/images/ui/text_images/ko/summary/summary_profile_profile_title_ko.png new file mode 100644 index 00000000000..deb57b96715 Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_profile_profile_title_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_stats_exp_title_ko.png b/public/images/ui/text_images/ko/summary/summary_stats_exp_title_ko.png new file mode 100644 index 00000000000..af0cb3afab8 Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_stats_exp_title_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_stats_expbar_title_ko.png b/public/images/ui/text_images/ko/summary/summary_stats_expbar_title_ko.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_stats_expbar_title_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_stats_item_title_ko.png b/public/images/ui/text_images/ko/summary/summary_stats_item_title_ko.png new file mode 100644 index 00000000000..6be5909e5f0 Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_stats_item_title_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_stats_stats_title_ko.png b/public/images/ui/text_images/ko/summary/summary_stats_stats_title_ko.png new file mode 100644 index 00000000000..371c2be4976 Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_stats_stats_title_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_tabs_1_ko.png b/public/images/ui/text_images/ko/summary/summary_tabs_1_ko.png new file mode 100644 index 00000000000..487d4a628ca Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_tabs_1_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_tabs_2_ko.png b/public/images/ui/text_images/ko/summary/summary_tabs_2_ko.png new file mode 100644 index 00000000000..304127ea2ef Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_tabs_2_ko.png differ diff --git a/public/images/ui/text_images/ko/summary/summary_tabs_3_ko.png b/public/images/ui/text_images/ko/summary/summary_tabs_3_ko.png new file mode 100644 index 00000000000..832acf4d5ba Binary files /dev/null and b/public/images/ui/text_images/ko/summary/summary_tabs_3_ko.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_dexnb_label_overlay_shiny_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_dexnb_label_overlay_shiny_pt-BR.png new file mode 100644 index 00000000000..54f0c3799a0 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_dexnb_label_overlay_shiny_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_dexnb_label_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_dexnb_label_pt-BR.png new file mode 100644 index 00000000000..5477e3385a8 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_dexnb_label_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_moves_descriptions_title_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_moves_descriptions_title_pt-BR.png new file mode 100644 index 00000000000..8d888143663 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_moves_descriptions_title_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_moves_effect_title_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_moves_effect_title_pt-BR.png new file mode 100644 index 00000000000..83190955f2c Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_moves_effect_title_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_moves_moves_title_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_moves_moves_title_pt-BR.png new file mode 100644 index 00000000000..0a2d1657750 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_moves_moves_title_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_moves_overlay_pp_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_moves_overlay_pp_pt-BR.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_moves_overlay_pp_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_profile_ability_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_profile_ability_pt-BR.png new file mode 100644 index 00000000000..28fbb5a8be9 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_profile_ability_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_profile_memo_title_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_profile_memo_title_pt-BR.png new file mode 100644 index 00000000000..b7ef7c91fc5 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_profile_memo_title_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_profile_passive_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_profile_passive_pt-BR.png new file mode 100644 index 00000000000..11616a74287 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_profile_passive_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_profile_profile_title_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_profile_profile_title_pt-BR.png new file mode 100644 index 00000000000..a5ed0e3e169 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_profile_profile_title_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_stats_exp_title_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_stats_exp_title_pt-BR.png new file mode 100644 index 00000000000..d66fa829be1 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_stats_exp_title_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_stats_expbar_title_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_stats_expbar_title_pt-BR.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_stats_expbar_title_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_stats_item_title_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_stats_item_title_pt-BR.png new file mode 100644 index 00000000000..b9ea9400a64 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_stats_item_title_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_stats_stats_title_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_stats_stats_title_pt-BR.png new file mode 100644 index 00000000000..bc9dffc2887 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_stats_stats_title_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_tabs_1_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_tabs_1_pt-BR.png new file mode 100644 index 00000000000..888e8042051 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_tabs_1_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_tabs_2_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_tabs_2_pt-BR.png new file mode 100644 index 00000000000..29cad435f2d Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_tabs_2_pt-BR.png differ diff --git a/public/images/ui/text_images/pt-BR/summary/summary_tabs_3_pt-BR.png b/public/images/ui/text_images/pt-BR/summary/summary_tabs_3_pt-BR.png new file mode 100644 index 00000000000..f4eebe1eb11 Binary files /dev/null and b/public/images/ui/text_images/pt-BR/summary/summary_tabs_3_pt-BR.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_dexnb_label_overlay_shiny_ro.png b/public/images/ui/text_images/ro/summary/summary_dexnb_label_overlay_shiny_ro.png new file mode 100644 index 00000000000..f35e327c29a Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_dexnb_label_overlay_shiny_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_dexnb_label_ro.png b/public/images/ui/text_images/ro/summary/summary_dexnb_label_ro.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_dexnb_label_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_moves_descriptions_title_ro.png b/public/images/ui/text_images/ro/summary/summary_moves_descriptions_title_ro.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_moves_descriptions_title_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_moves_effect_title_ro.png b/public/images/ui/text_images/ro/summary/summary_moves_effect_title_ro.png new file mode 100644 index 00000000000..fbbaac0b260 Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_moves_effect_title_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_moves_moves_title_ro.png b/public/images/ui/text_images/ro/summary/summary_moves_moves_title_ro.png new file mode 100644 index 00000000000..6bbb29c9c5f Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_moves_moves_title_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_moves_overlay_pp_ro.png b/public/images/ui/text_images/ro/summary/summary_moves_overlay_pp_ro.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_moves_overlay_pp_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_profile_ability_ro.png b/public/images/ui/text_images/ro/summary/summary_profile_ability_ro.png new file mode 100644 index 00000000000..a05c22b7d47 Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_profile_ability_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_profile_memo_title_ro.png b/public/images/ui/text_images/ro/summary/summary_profile_memo_title_ro.png new file mode 100644 index 00000000000..3d69c20e57f Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_profile_memo_title_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_profile_passive_ro.png b/public/images/ui/text_images/ro/summary/summary_profile_passive_ro.png new file mode 100644 index 00000000000..c026e87a215 Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_profile_passive_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_profile_profile_title_ro.png b/public/images/ui/text_images/ro/summary/summary_profile_profile_title_ro.png new file mode 100644 index 00000000000..4170dccf682 Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_profile_profile_title_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_stats_exp_title_ro.png b/public/images/ui/text_images/ro/summary/summary_stats_exp_title_ro.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_stats_exp_title_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_stats_expbar_title_ro.png b/public/images/ui/text_images/ro/summary/summary_stats_expbar_title_ro.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_stats_expbar_title_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_stats_item_title_ro.png b/public/images/ui/text_images/ro/summary/summary_stats_item_title_ro.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_stats_item_title_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_stats_stats_title_ro.png b/public/images/ui/text_images/ro/summary/summary_stats_stats_title_ro.png new file mode 100644 index 00000000000..f602a43c39d Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_stats_stats_title_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_tabs_1_ro.png b/public/images/ui/text_images/ro/summary/summary_tabs_1_ro.png new file mode 100644 index 00000000000..750c407b075 Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_tabs_1_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_tabs_2_ro.png b/public/images/ui/text_images/ro/summary/summary_tabs_2_ro.png new file mode 100644 index 00000000000..50c1db1f34c Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_tabs_2_ro.png differ diff --git a/public/images/ui/text_images/ro/summary/summary_tabs_3_ro.png b/public/images/ui/text_images/ro/summary/summary_tabs_3_ro.png new file mode 100644 index 00000000000..24676712fb9 Binary files /dev/null and b/public/images/ui/text_images/ro/summary/summary_tabs_3_ro.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_dexnb_label_overlay_shiny_ru.png b/public/images/ui/text_images/ru/summary/summary_dexnb_label_overlay_shiny_ru.png new file mode 100644 index 00000000000..1ba0191881d Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_dexnb_label_overlay_shiny_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_dexnb_label_ru.png b/public/images/ui/text_images/ru/summary/summary_dexnb_label_ru.png new file mode 100644 index 00000000000..2a2e66426cb Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_dexnb_label_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_moves_descriptions_title_ru.png b/public/images/ui/text_images/ru/summary/summary_moves_descriptions_title_ru.png new file mode 100644 index 00000000000..a435d6d845e Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_moves_descriptions_title_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_moves_effect_title_ru.png b/public/images/ui/text_images/ru/summary/summary_moves_effect_title_ru.png new file mode 100644 index 00000000000..8bd4b965247 Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_moves_effect_title_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_moves_moves_title_ru.png b/public/images/ui/text_images/ru/summary/summary_moves_moves_title_ru.png new file mode 100644 index 00000000000..94afd3226e8 Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_moves_moves_title_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_moves_overlay_pp_ru.png b/public/images/ui/text_images/ru/summary/summary_moves_overlay_pp_ru.png new file mode 100644 index 00000000000..dbdc2275129 Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_moves_overlay_pp_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_profile_ability_ru.png b/public/images/ui/text_images/ru/summary/summary_profile_ability_ru.png new file mode 100644 index 00000000000..ddfcc6102dc Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_profile_ability_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_profile_memo_title_ru.png b/public/images/ui/text_images/ru/summary/summary_profile_memo_title_ru.png new file mode 100644 index 00000000000..743a2f36454 Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_profile_memo_title_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_profile_passive_ru.png b/public/images/ui/text_images/ru/summary/summary_profile_passive_ru.png new file mode 100644 index 00000000000..29179b6d75b Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_profile_passive_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_profile_profile_title_ru.png b/public/images/ui/text_images/ru/summary/summary_profile_profile_title_ru.png new file mode 100644 index 00000000000..77edb538634 Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_profile_profile_title_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_stats_exp_title_ru.png b/public/images/ui/text_images/ru/summary/summary_stats_exp_title_ru.png new file mode 100644 index 00000000000..e058eaa917e Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_stats_exp_title_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_stats_expbar_title_ru.png b/public/images/ui/text_images/ru/summary/summary_stats_expbar_title_ru.png new file mode 100644 index 00000000000..424a5378f7e Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_stats_expbar_title_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_stats_item_title_ru.png b/public/images/ui/text_images/ru/summary/summary_stats_item_title_ru.png new file mode 100644 index 00000000000..95b01d062ab Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_stats_item_title_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_stats_stats_title_ru.png b/public/images/ui/text_images/ru/summary/summary_stats_stats_title_ru.png new file mode 100644 index 00000000000..0c1c5dc9445 Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_stats_stats_title_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_tabs_1_ru.png b/public/images/ui/text_images/ru/summary/summary_tabs_1_ru.png new file mode 100644 index 00000000000..1fef6034ad7 Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_tabs_1_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_tabs_2_ru.png b/public/images/ui/text_images/ru/summary/summary_tabs_2_ru.png new file mode 100644 index 00000000000..0382fc880a9 Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_tabs_2_ru.png differ diff --git a/public/images/ui/text_images/ru/summary/summary_tabs_3_ru.png b/public/images/ui/text_images/ru/summary/summary_tabs_3_ru.png new file mode 100644 index 00000000000..1395ac840af Binary files /dev/null and b/public/images/ui/text_images/ru/summary/summary_tabs_3_ru.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_dexnb_label_overlay_shiny_tl.png b/public/images/ui/text_images/tl/summary/summary_dexnb_label_overlay_shiny_tl.png new file mode 100644 index 00000000000..f35e327c29a Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_dexnb_label_overlay_shiny_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_dexnb_label_tl.png b/public/images/ui/text_images/tl/summary/summary_dexnb_label_tl.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_dexnb_label_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_moves_descriptions_title_tl.png b/public/images/ui/text_images/tl/summary/summary_moves_descriptions_title_tl.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_moves_descriptions_title_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_moves_effect_title_tl.png b/public/images/ui/text_images/tl/summary/summary_moves_effect_title_tl.png new file mode 100644 index 00000000000..fbbaac0b260 Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_moves_effect_title_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_moves_moves_title_tl.png b/public/images/ui/text_images/tl/summary/summary_moves_moves_title_tl.png new file mode 100644 index 00000000000..6bbb29c9c5f Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_moves_moves_title_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_moves_overlay_pp_tl.png b/public/images/ui/text_images/tl/summary/summary_moves_overlay_pp_tl.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_moves_overlay_pp_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_profile_ability_tl.png b/public/images/ui/text_images/tl/summary/summary_profile_ability_tl.png new file mode 100644 index 00000000000..a05c22b7d47 Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_profile_ability_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_profile_memo_title_tl.png b/public/images/ui/text_images/tl/summary/summary_profile_memo_title_tl.png new file mode 100644 index 00000000000..3d69c20e57f Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_profile_memo_title_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_profile_passive_tl.png b/public/images/ui/text_images/tl/summary/summary_profile_passive_tl.png new file mode 100644 index 00000000000..c026e87a215 Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_profile_passive_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_profile_profile_title_tl.png b/public/images/ui/text_images/tl/summary/summary_profile_profile_title_tl.png new file mode 100644 index 00000000000..4170dccf682 Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_profile_profile_title_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_stats_exp_title_tl.png b/public/images/ui/text_images/tl/summary/summary_stats_exp_title_tl.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_stats_exp_title_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_stats_expbar_title_tl.png b/public/images/ui/text_images/tl/summary/summary_stats_expbar_title_tl.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_stats_expbar_title_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_stats_item_title_tl.png b/public/images/ui/text_images/tl/summary/summary_stats_item_title_tl.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_stats_item_title_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_stats_stats_title_tl.png b/public/images/ui/text_images/tl/summary/summary_stats_stats_title_tl.png new file mode 100644 index 00000000000..f602a43c39d Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_stats_stats_title_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_tabs_1_tl.png b/public/images/ui/text_images/tl/summary/summary_tabs_1_tl.png new file mode 100644 index 00000000000..750c407b075 Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_tabs_1_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_tabs_2_tl.png b/public/images/ui/text_images/tl/summary/summary_tabs_2_tl.png new file mode 100644 index 00000000000..50c1db1f34c Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_tabs_2_tl.png differ diff --git a/public/images/ui/text_images/tl/summary/summary_tabs_3_tl.png b/public/images/ui/text_images/tl/summary/summary_tabs_3_tl.png new file mode 100644 index 00000000000..24676712fb9 Binary files /dev/null and b/public/images/ui/text_images/tl/summary/summary_tabs_3_tl.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_dexnb_label_overlay_shiny_tr.png b/public/images/ui/text_images/tr/summary/summary_dexnb_label_overlay_shiny_tr.png new file mode 100644 index 00000000000..f35e327c29a Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_dexnb_label_overlay_shiny_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_dexnb_label_tr.png b/public/images/ui/text_images/tr/summary/summary_dexnb_label_tr.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_dexnb_label_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_moves_descriptions_title_tr.png b/public/images/ui/text_images/tr/summary/summary_moves_descriptions_title_tr.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_moves_descriptions_title_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_moves_effect_title_tr.png b/public/images/ui/text_images/tr/summary/summary_moves_effect_title_tr.png new file mode 100644 index 00000000000..fbbaac0b260 Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_moves_effect_title_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_moves_moves_title_tr.png b/public/images/ui/text_images/tr/summary/summary_moves_moves_title_tr.png new file mode 100644 index 00000000000..6bbb29c9c5f Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_moves_moves_title_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_moves_overlay_pp_tr.png b/public/images/ui/text_images/tr/summary/summary_moves_overlay_pp_tr.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_moves_overlay_pp_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_profile_ability_tr.png b/public/images/ui/text_images/tr/summary/summary_profile_ability_tr.png new file mode 100644 index 00000000000..a05c22b7d47 Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_profile_ability_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_profile_memo_title_tr.png b/public/images/ui/text_images/tr/summary/summary_profile_memo_title_tr.png new file mode 100644 index 00000000000..3d69c20e57f Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_profile_memo_title_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_profile_passive_tr.png b/public/images/ui/text_images/tr/summary/summary_profile_passive_tr.png new file mode 100644 index 00000000000..c026e87a215 Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_profile_passive_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_profile_profile_title_tr.png b/public/images/ui/text_images/tr/summary/summary_profile_profile_title_tr.png new file mode 100644 index 00000000000..4170dccf682 Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_profile_profile_title_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_stats_exp_title_tr.png b/public/images/ui/text_images/tr/summary/summary_stats_exp_title_tr.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_stats_exp_title_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_stats_expbar_title_tr.png b/public/images/ui/text_images/tr/summary/summary_stats_expbar_title_tr.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_stats_expbar_title_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_stats_item_title_tr.png b/public/images/ui/text_images/tr/summary/summary_stats_item_title_tr.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_stats_item_title_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_stats_stats_title_tr.png b/public/images/ui/text_images/tr/summary/summary_stats_stats_title_tr.png new file mode 100644 index 00000000000..f602a43c39d Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_stats_stats_title_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_tabs_1_tr.png b/public/images/ui/text_images/tr/summary/summary_tabs_1_tr.png new file mode 100644 index 00000000000..750c407b075 Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_tabs_1_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_tabs_2_tr.png b/public/images/ui/text_images/tr/summary/summary_tabs_2_tr.png new file mode 100644 index 00000000000..50c1db1f34c Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_tabs_2_tr.png differ diff --git a/public/images/ui/text_images/tr/summary/summary_tabs_3_tr.png b/public/images/ui/text_images/tr/summary/summary_tabs_3_tr.png new file mode 100644 index 00000000000..24676712fb9 Binary files /dev/null and b/public/images/ui/text_images/tr/summary/summary_tabs_3_tr.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_dexnb_label_overlay_shiny_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_dexnb_label_overlay_shiny_zh-CN.png new file mode 100644 index 00000000000..f35e327c29a Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_dexnb_label_overlay_shiny_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_dexnb_label_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_dexnb_label_zh-CN.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_dexnb_label_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_moves_descriptions_title_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_moves_descriptions_title_zh-CN.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_moves_descriptions_title_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_moves_effect_title_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_moves_effect_title_zh-CN.png new file mode 100644 index 00000000000..fbbaac0b260 Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_moves_effect_title_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_moves_moves_title_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_moves_moves_title_zh-CN.png new file mode 100644 index 00000000000..6bbb29c9c5f Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_moves_moves_title_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_moves_overlay_pp_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_moves_overlay_pp_zh-CN.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_moves_overlay_pp_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_profile_ability_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_profile_ability_zh-CN.png new file mode 100644 index 00000000000..a05c22b7d47 Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_profile_ability_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_profile_memo_title_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_profile_memo_title_zh-CN.png new file mode 100644 index 00000000000..3d69c20e57f Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_profile_memo_title_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_profile_passive_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_profile_passive_zh-CN.png new file mode 100644 index 00000000000..c026e87a215 Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_profile_passive_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_profile_profile_title_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_profile_profile_title_zh-CN.png new file mode 100644 index 00000000000..4170dccf682 Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_profile_profile_title_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_stats_exp_title_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_stats_exp_title_zh-CN.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_stats_exp_title_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_stats_expbar_title_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_stats_expbar_title_zh-CN.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_stats_expbar_title_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_stats_item_title_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_stats_item_title_zh-CN.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_stats_item_title_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_stats_stats_title_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_stats_stats_title_zh-CN.png new file mode 100644 index 00000000000..f602a43c39d Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_stats_stats_title_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_tabs_1_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_tabs_1_zh-CN.png new file mode 100644 index 00000000000..750c407b075 Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_tabs_1_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_tabs_2_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_tabs_2_zh-CN.png new file mode 100644 index 00000000000..50c1db1f34c Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_tabs_2_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-CN/summary/summary_tabs_3_zh-CN.png b/public/images/ui/text_images/zh-CN/summary/summary_tabs_3_zh-CN.png new file mode 100644 index 00000000000..24676712fb9 Binary files /dev/null and b/public/images/ui/text_images/zh-CN/summary/summary_tabs_3_zh-CN.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_dexnb_label_overlay_shiny_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_dexnb_label_overlay_shiny_zh-TW.png new file mode 100644 index 00000000000..f35e327c29a Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_dexnb_label_overlay_shiny_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_dexnb_label_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_dexnb_label_zh-TW.png new file mode 100644 index 00000000000..bf568c486aa Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_dexnb_label_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_moves_descriptions_title_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_moves_descriptions_title_zh-TW.png new file mode 100644 index 00000000000..e83e8cafbfc Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_moves_descriptions_title_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_moves_effect_title_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_moves_effect_title_zh-TW.png new file mode 100644 index 00000000000..fbbaac0b260 Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_moves_effect_title_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_moves_moves_title_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_moves_moves_title_zh-TW.png new file mode 100644 index 00000000000..6bbb29c9c5f Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_moves_moves_title_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_moves_overlay_pp_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_moves_overlay_pp_zh-TW.png new file mode 100644 index 00000000000..a2bcd0bd021 Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_moves_overlay_pp_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_profile_ability_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_profile_ability_zh-TW.png new file mode 100644 index 00000000000..a05c22b7d47 Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_profile_ability_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_profile_memo_title_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_profile_memo_title_zh-TW.png new file mode 100644 index 00000000000..3d69c20e57f Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_profile_memo_title_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_profile_passive_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_profile_passive_zh-TW.png new file mode 100644 index 00000000000..c026e87a215 Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_profile_passive_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_profile_profile_title_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_profile_profile_title_zh-TW.png new file mode 100644 index 00000000000..4170dccf682 Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_profile_profile_title_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_stats_exp_title_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_stats_exp_title_zh-TW.png new file mode 100644 index 00000000000..d0d8d7f81a1 Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_stats_exp_title_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_stats_expbar_title_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_stats_expbar_title_zh-TW.png new file mode 100644 index 00000000000..4889b64eca8 Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_stats_expbar_title_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_stats_item_title_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_stats_item_title_zh-TW.png new file mode 100644 index 00000000000..42e08b3e52a Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_stats_item_title_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_stats_stats_title_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_stats_stats_title_zh-TW.png new file mode 100644 index 00000000000..f602a43c39d Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_stats_stats_title_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_tabs_1_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_tabs_1_zh-TW.png new file mode 100644 index 00000000000..750c407b075 Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_tabs_1_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_tabs_2_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_tabs_2_zh-TW.png new file mode 100644 index 00000000000..50c1db1f34c Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_tabs_2_zh-TW.png differ diff --git a/public/images/ui/text_images/zh-TW/summary/summary_tabs_3_zh-TW.png b/public/images/ui/text_images/zh-TW/summary/summary_tabs_3_zh-TW.png new file mode 100644 index 00000000000..24676712fb9 Binary files /dev/null and b/public/images/ui/text_images/zh-TW/summary/summary_tabs_3_zh-TW.png differ diff --git a/public/locales b/public/locales index 58fa5f9b6e9..2686cd3edc0 160000 --- a/public/locales +++ b/public/locales @@ -1 +1 @@ -Subproject commit 58fa5f9b6e94469017bfbe69bef992ed48ef5343 +Subproject commit 2686cd3edc0bd2c7a7f12cc54c00c109e51a48d7 diff --git a/public/service-worker.js b/public/service-worker.js index b45d2484709..ff380adca73 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,3 +1,7 @@ self.addEventListener('install', function () { console.log('Service worker installing...'); }); + +self.addEventListener('activate', (event) => { + event.waitUntil(self.clients.claim()); +}) \ No newline at end of file diff --git a/src/@types/arena-tags.ts b/src/@types/arena-tags.ts index 4ac7abf6f3d..390d95a7daa 100644 --- a/src/@types/arena-tags.ts +++ b/src/@types/arena-tags.ts @@ -2,6 +2,7 @@ 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"; +import type { ObjectValues } from "#types/type-helpers"; /** 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 EntryHazardTagType = @@ -24,22 +25,32 @@ export type TurnProtectArenaTagType = /** 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}. */ +/** Subset of {@linkcode ArenaTagType}s that are **not** able to persist across turns, and should therefore not be serialized in {@linkcode SessionSaveData}. */ export type NonSerializableArenaTagType = ArenaTagType.NONE | TurnProtectArenaTagType | ArenaTagType.ION_DELUGE; /** Subset of {@linkcode ArenaTagType}s that may persist across turns, and thus must be serialized in {@linkcode SessionSaveData}. */ export type SerializableArenaTagType = Exclude; /** - * Type-safe representation of an arbitrary, serialized Arena Tag + * Utility type containing all entries of {@linkcode ArenaTagTypeMap} corresponding to serializable tags. */ -export type ArenaTagTypeData = Parameters< - ArenaTagTypeMap[keyof { - [K in keyof ArenaTagTypeMap as K extends SerializableArenaTagType ? K : never]: ArenaTagTypeMap[K]; - }]["loadTag"] ->[0]; +type SerializableArenaTagTypeMap = Pick; -/** Dummy, typescript-only declaration to ensure that +/** + * Type mapping all `ArenaTag`s to type-safe representations of their serialized forms. + * @interface + */ +export type ArenaTagDataMap = { + [k in keyof SerializableArenaTagTypeMap]: Parameters[0]; +}; + +/** + * Type-safe representation of an arbitrary, serialized `ArenaTag`. + */ +export type ArenaTagData = ObjectValues; + +/** + * Dummy, typescript-only declaration to ensure that * {@linkcode ArenaTagTypeMap} has a map for all ArenaTagTypes. * * If an arena tag is missing from the map, typescript will throw an error on this statement. diff --git a/src/@types/battler-tags.ts b/src/@types/battler-tags.ts index 211eb25113d..8e34108958e 100644 --- a/src/@types/battler-tags.ts +++ b/src/@types/battler-tags.ts @@ -1,8 +1,11 @@ // biome-ignore-start lint/correctness/noUnusedImports: Used in a TSDoc comment import type { AbilityBattlerTag, BattlerTagTypeMap, SerializableBattlerTag, TypeBoostTag } from "#data/battler-tags"; import type { AbilityId } from "#enums/ability-id"; -// biome-ignore-end lint/correctness/noUnusedImports: end +import type { SessionSaveData } from "#system/game-data"; +// biome-ignore-end lint/correctness/noUnusedImports: Used in a TSDoc comment + import type { BattlerTagType } from "#enums/battler-tag-type"; +import type { InferKeys, ObjectValues } from "#types/type-helpers"; /** * Subset of {@linkcode BattlerTagType}s that restrict the use of moves. @@ -103,28 +106,35 @@ export type RemovedTypeTagType = BattlerTagType.DOUBLE_SHOCKED | BattlerTagType. export type HighestStatBoostTagType = | BattlerTagType.QUARK_DRIVE // formatting | BattlerTagType.PROTOSYNTHESIS; -/** - * Subset of {@linkcode BattlerTagType}s that are able to persist between turns and should therefore be serialized - */ -export type SerializableBattlerTagType = keyof { - [K in keyof BattlerTagTypeMap as BattlerTagTypeMap[K] extends SerializableBattlerTag - ? K - : never]: BattlerTagTypeMap[K]; -}; /** - * Subset of {@linkcode BattlerTagType}s that are not able to persist across waves and should therefore not be serialized + * Subset of {@linkcode BattlerTagType}s that are able to persist between turns, and should therefore be serialized. + */ +export type SerializableBattlerTagType = InferKeys; + +/** + * Subset of {@linkcode BattlerTagType}s that are **not** able to persist between turns, + * and should therefore not be serialized in {@linkcode SessionSaveData}. */ export type NonSerializableBattlerTagType = Exclude; /** - * Type-safe representation of an arbitrary, serialized Battler Tag + * Utility type containing all entries of {@linkcode BattlerTagTypeMap} corresponding to serializable tags. */ -export type BattlerTagTypeData = Parameters< - BattlerTagTypeMap[keyof { - [K in keyof BattlerTagTypeMap as K extends SerializableBattlerTagType ? K : never]: BattlerTagTypeMap[K]; - }]["loadTag"] ->[0]; +type SerializableBattlerTagTypeMap = Pick; + +/** + * Type mapping all `BattlerTag`s to type-safe representations of their serialized forms. + * @interface + */ +export type BattlerTagDataMap = { + [k in keyof SerializableBattlerTagTypeMap]: Parameters[0]; +}; + +/** + * Type-safe representation of an arbitrary, serialized `BattlerTag`. + */ +export type BattlerTagData = ObjectValues; /** * Dummy, typescript-only declaration to ensure that diff --git a/src/@types/helpers/type-helpers.ts b/src/@types/helpers/type-helpers.ts index 0be391aa3c4..048a86ab489 100644 --- a/src/@types/helpers/type-helpers.ts +++ b/src/@types/helpers/type-helpers.ts @@ -36,15 +36,18 @@ export type Mutable = { /** * Type helper to obtain the keys associated with a given value inside an object. + * Acts similar to {@linkcode Pick}, except checking the object's values instead of its keys. * @typeParam O - The type of the object - * @typeParam V - The type of one of O's values + * @typeParam V - The type of one of O's values. */ -export type InferKeys> = { - [K in keyof O]: O[K] extends V ? K : never; -}[keyof O]; +export type InferKeys = V extends ObjectValues + ? { + [K in keyof O]: O[K] extends V ? K : never; + }[keyof O] + : never; /** - * Utility type to obtain the values of a given object. \ + * Utility type to obtain a union of the values of a given object. \ * Functions similar to `keyof E`, except producing the values instead of the keys. * @remarks * This can be used to convert an `enum` interface produced by `typeof Enum` into the union type representing its members. diff --git a/src/battle-scene.ts b/src/battle-scene.ts index be02962867c..9bb76b6fd23 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1476,10 +1476,7 @@ export class BattleScene extends SceneBase { pokemon.resetBattleAndWaveData(); pokemon.resetTera(); applyAbAttrs("PostBattleInitAbAttr", { pokemon }); - if ( - pokemon.hasSpecies(SpeciesId.TERAPAGOS) || - (this.gameMode.isClassic && this.currentBattle.waveIndex > 180 && this.currentBattle.waveIndex <= 190) - ) { + if (pokemon.hasSpecies(SpeciesId.TERAPAGOS)) { this.arena.playerTerasUsed = 0; } } @@ -1564,9 +1561,9 @@ export class BattleScene extends SceneBase { return 0; } - const isEggPhase: boolean = ["EggLapsePhase", "EggHatchPhase"].includes( - this.phaseManager.getCurrentPhase()?.phaseName ?? "", - ); + const isEggPhase = + this.phaseManager.getCurrentPhase().is("EggLapsePhase") || + this.phaseManager.getCurrentPhase().is("EggHatchPhase"); if ( // Give trainers with specialty types an appropriately-typed form for Wormadam, Rotom, Arceus, Oricorio, Silvally, or Paldean Tauros. @@ -2318,7 +2315,7 @@ export class BattleScene extends SceneBase { }); } - playSound(sound: string | AnySound, config?: object): AnySound { + playSound(sound: string | AnySound, config?: object): AnySound | null { const key = typeof sound === "string" ? sound : sound.key; config = config ?? {}; try { @@ -2354,16 +2351,19 @@ export class BattleScene extends SceneBase { this.sound.play(key, config); return this.sound.get(key) as AnySound; } catch { - console.log(`${key} not found`); - return sound as AnySound; + console.warn(`${key} not found`); + return null; } } - playSoundWithoutBgm(soundName: string, pauseDuration?: number): AnySound { + playSoundWithoutBgm(soundName: string, pauseDuration?: number): AnySound | null { this.bgmCache.add(soundName); const resumeBgm = this.pauseBgm(); this.playSound(soundName); - const sound = this.sound.get(soundName) as AnySound; + const sound = this.sound.get(soundName); + if (!sound) { + return sound; + } if (this.bgmResumeTimer) { this.bgmResumeTimer.destroy(); } @@ -2373,7 +2373,7 @@ export class BattleScene extends SceneBase { this.bgmResumeTimer = null; }); } - return sound; + return sound as AnySound; } /** The loop point of any given battle, mystery encounter, or title track, read as seconds and milliseconds. */ diff --git a/src/constants.ts b/src/constants.ts index 589a091153c..17cf08aa7e2 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -53,12 +53,6 @@ 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 d73c1e12754..ad84348fe0c 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -968,6 +968,8 @@ export class MoveImmunityStatStageChangeAbAttr extends MoveImmunityAbAttr { export interface PostMoveInteractionAbAttrParams extends AugmentMoveInteractionAbAttrParams { /** Stores the hit result of the move used in the interaction */ readonly hitResult: HitResult; + /** The amount of damage dealt in the interaction */ + readonly damage: number; } export class PostDefendAbAttr extends AbAttr { @@ -1077,20 +1079,16 @@ export class PostDefendHpGatedStatStageChangeAbAttr extends PostDefendAbAttr { this.selfTarget = selfTarget; } - override canApply({ pokemon, opponent: attacker, move }: PostMoveInteractionAbAttrParams): boolean { + override canApply({ pokemon, opponent: attacker, move, damage }: PostMoveInteractionAbAttrParams): boolean { const hpGateFlat: number = Math.ceil(pokemon.getMaxHp() * this.hpGate); - const lastAttackReceived = pokemon.turnData.attacksReceived[pokemon.turnData.attacksReceived.length - 1]; - const damageReceived = lastAttackReceived?.damage || 0; - return ( - this.condition(pokemon, attacker, move) && pokemon.hp <= hpGateFlat && pokemon.hp + damageReceived > hpGateFlat - ); + return this.condition(pokemon, attacker, move) && pokemon.hp <= hpGateFlat && pokemon.hp + damage > hpGateFlat; } - override apply({ simulated, pokemon, opponent: attacker }: PostMoveInteractionAbAttrParams): void { + override apply({ simulated, pokemon, opponent }: PostMoveInteractionAbAttrParams): void { if (!simulated) { globalScene.phaseManager.unshiftNew( "StatStageChangePhase", - (this.selfTarget ? pokemon : attacker).getBattlerIndex(), + (this.selfTarget ? pokemon : opponent).getBattlerIndex(), true, this.stats, this.stages, @@ -1261,17 +1259,17 @@ export class PostDefendContactApplyTagChanceAbAttr extends PostDefendAbAttr { this.turnCount = turnCount; } - override canApply({ move, pokemon, opponent: attacker }: PostMoveInteractionAbAttrParams): boolean { + override canApply({ move, pokemon, opponent }: PostMoveInteractionAbAttrParams): boolean { return ( - move.doesFlagEffectApply({ flag: MoveFlags.MAKES_CONTACT, user: attacker, target: pokemon }) && + move.doesFlagEffectApply({ flag: MoveFlags.MAKES_CONTACT, user: opponent, target: pokemon }) && pokemon.randBattleSeedInt(100) < this.chance && - attacker.canAddTag(this.tagType) + opponent.canAddTag(this.tagType) ); } - override apply({ simulated, opponent: attacker, move }: PostMoveInteractionAbAttrParams): void { + override apply({ pokemon, simulated, opponent, move }: PostMoveInteractionAbAttrParams): void { if (!simulated) { - attacker.addTag(this.tagType, this.turnCount, move.id, attacker.id); + opponent.addTag(this.tagType, this.turnCount, move.id, pokemon.id); } } } @@ -3012,41 +3010,44 @@ export class PostSummonFormChangeAbAttr extends PostSummonAbAttr { } } -/** Attempts to copy a pokemon's ability */ +/** + * Attempts to copy a pokemon's ability + * + * @remarks + * Hardcodes idiosyncrasies specific to trace, so should not be used for other abilities + * that might copy abilities in the future + * @sealed + */ export class PostSummonCopyAbilityAbAttr extends PostSummonAbAttr { private target: Pokemon; private targetAbilityName: string; - override canApply({ pokemon }: AbAttrBaseParams): boolean { - const targets = pokemon.getOpponents(); + override canApply({ pokemon, simulated }: AbAttrBaseParams): boolean { + const targets = pokemon + .getOpponents() + .filter(t => t.getAbility().isCopiable || t.getAbility().id === AbilityId.WONDER_GUARD); if (!targets.length) { return false; } let target: Pokemon; - if (targets.length > 1) { - globalScene.executeWithSeedOffset(() => (target = randSeedItem(targets)), globalScene.currentBattle.waveIndex); + // simulated call always chooses first target so as to not advance RNG + if (targets.length > 1 && !simulated) { + target = targets[randSeedInt(targets.length)]; } else { target = targets[0]; } - if ( - !target!.getAbility().isCopiable && - // Wonder Guard is normally uncopiable so has the attribute, but Trace specifically can copy it - !(pokemon.hasAbility(AbilityId.TRACE) && target!.getAbility().id === AbilityId.WONDER_GUARD) - ) { - return false; - } - - this.target = target!; - this.targetAbilityName = allAbilities[target!.getAbility().id].name; + this.target = target; + this.targetAbilityName = allAbilities[target.getAbility().id].name; return true; } override apply({ pokemon, simulated }: AbAttrBaseParams): void { - if (!simulated) { - pokemon.setTempAbility(this.target!.getAbility()); - setAbilityRevealed(this.target!); + // Protect against this somehow being called before canApply by ensuring target is defined + if (!simulated && this.target) { + pokemon.setTempAbility(this.target.getAbility()); + setAbilityRevealed(this.target); pokemon.updateInfo(); } } @@ -4782,7 +4783,7 @@ export class MoodyAbAttr extends PostTurnAbAttr { if (!simulated) { if (canRaise.length > 0) { const raisedStat = canRaise[pokemon.randBattleSeedInt(canRaise.length)]; - canLower = canRaise.filter(s => s !== raisedStat); + canLower = canLower.filter(s => s !== raisedStat); globalScene.phaseManager.unshiftNew("StatStageChangePhase", pokemon.getBattlerIndex(), true, [raisedStat], 2); } if (canLower.length > 0) { diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index 2a995d749eb..fd5ab607195 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -23,7 +23,7 @@ import type { Arena } from "#field/arena"; import type { Pokemon } from "#field/pokemon"; import type { ArenaScreenTagType, - ArenaTagTypeData, + ArenaTagData, EntryHazardTagType, RoomArenaTagType, SerializableArenaTagType, @@ -471,7 +471,7 @@ const QuickGuardConditionFunc: ProtectConditionFunc = (_arena, moveId) => { const move = allMoves[moveId]; const effectPhase = globalScene.phaseManager.getCurrentPhase(); - if (effectPhase?.is("MoveEffectPhase")) { + if (effectPhase.is("MoveEffectPhase")) { const attacker = effectPhase.getUserPokemon(); if (attacker) { return move.getPriority(attacker) > 0; @@ -937,7 +937,7 @@ class StealthRockTag extends DamagingTrapTag { protected override getTriggerMessage(pokemon: Pokemon): string { return i18next.t("arenaTag:stealthRockActivateTrap", { - pokemonName: getPokemonNameWithAffix(pokemon), + pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), }); } @@ -1663,7 +1663,7 @@ export function getArenaTag( * @param source - An arena tag * @returns The valid arena tag */ -export function loadArenaTag(source: ArenaTag | ArenaTagTypeData | { tagType: ArenaTagType.NONE }): ArenaTag { +export function loadArenaTag(source: ArenaTag | ArenaTagData | { tagType: ArenaTagType.NONE }): ArenaTag { if (source.tagType === ArenaTagType.NONE) { return new NoneTag(); } diff --git a/src/data/balance/egg-moves.ts b/src/data/balance/egg-moves.ts index 2d2e981219d..5dd7bcbd9e2 100644 --- a/src/data/balance/egg-moves.ts +++ b/src/data/balance/egg-moves.ts @@ -187,7 +187,7 @@ export const speciesEggMoves = { [SpeciesId.WYNAUT]: [ MoveId.RECOVER, MoveId.SHED_TAIL, MoveId.TAUNT, MoveId.COMEUPPANCE ], [SpeciesId.SNORUNT]: [ MoveId.SPARKLY_SWIRL, MoveId.NASTY_PLOT, MoveId.EARTH_POWER, MoveId.BLOOD_MOON ], [SpeciesId.SPHEAL]: [ MoveId.FLIP_TURN, MoveId.FREEZE_DRY, MoveId.SLACK_OFF, MoveId.STEAM_ERUPTION ], - [SpeciesId.CLAMPERL]: [ MoveId.SHELL_SIDE_ARM, MoveId.BOUNCY_BUBBLE, MoveId.FREEZE_DRY, MoveId.STEAM_ERUPTION ], + [SpeciesId.CLAMPERL]: [ MoveId.SHELL_SIDE_ARM, MoveId.SNIPE_SHOT, MoveId.GIGA_DRAIN, MoveId.BOUNCY_BUBBLE ], [SpeciesId.RELICANTH]: [ MoveId.DRAGON_DANCE, MoveId.SHORE_UP, MoveId.WAVE_CRASH, MoveId.DIAMOND_STORM ], [SpeciesId.LUVDISC]: [ MoveId.BATON_PASS, MoveId.HEART_SWAP, MoveId.GLITZY_GLOW, MoveId.REVIVAL_BLESSING ], [SpeciesId.BAGON]: [ MoveId.HEADLONG_RUSH, MoveId.FIRE_LASH, MoveId.DRAGON_DANCE, MoveId.DRAGON_DARTS ], diff --git a/src/data/balance/passives.ts b/src/data/balance/passives.ts index 0e34917fd80..1297ad71c36 100644 --- a/src/data/balance/passives.ts +++ b/src/data/balance/passives.ts @@ -402,7 +402,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.SPHEAL]: { 0: AbilityId.UNAWARE }, [SpeciesId.SEALEO]: { 0: AbilityId.UNAWARE }, [SpeciesId.WALREIN]: { 0: AbilityId.UNAWARE }, - [SpeciesId.CLAMPERL]: { 0: AbilityId.DAUNTLESS_SHIELD }, + [SpeciesId.CLAMPERL]: { 0: AbilityId.OVERCOAT }, [SpeciesId.GOREBYSS]: { 0: AbilityId.ARENA_TRAP }, [SpeciesId.HUNTAIL]: { 0: AbilityId.ARENA_TRAP }, [SpeciesId.RELICANTH]: { 0: AbilityId.PRIMORDIAL_SEA }, diff --git a/src/data/balance/pokemon-evolutions.ts b/src/data/balance/pokemon-evolutions.ts index d42bce041c2..bf588784f24 100644 --- a/src/data/balance/pokemon-evolutions.ts +++ b/src/data/balance/pokemon-evolutions.ts @@ -1,3 +1,4 @@ +import { defaultStarterSpecies } from "#app/constants"; import { globalScene } from "#app/global-scene"; import { speciesStarterCosts } from "#balance/starters"; import { allMoves } from "#data/data-lists"; @@ -76,7 +77,8 @@ export enum EvolutionItem { LEADERS_CREST } -type TyrogueMove = MoveId.LOW_SWEEP | MoveId.MACH_PUNCH | MoveId.RAPID_SPIN; +const tyrogueMoves = [MoveId.LOW_SWEEP, MoveId.MACH_PUNCH, MoveId.RAPID_SPIN] as const; +type TyrogueMove = typeof tyrogueMoves[number]; /** * Pokemon Evolution tuple type consisting of: @@ -191,7 +193,7 @@ export class SpeciesEvolutionCondition { case EvoCondKey.WEATHER: return cond.weather.includes(globalScene.arena.getWeatherType()); case EvoCondKey.TYROGUE: - return pokemon.getMoveset(true).find(m => m.moveId as TyrogueMove)?.moveId === cond.move; + return pokemon.getMoveset(true).find(m => (tyrogueMoves as readonly MoveId[]) .includes(m.moveId))?.moveId === cond.move; case EvoCondKey.NATURE: return cond.nature.includes(pokemon.getNature()); case EvoCondKey.RANDOM_FORM: { @@ -1883,6 +1885,15 @@ export function initPokemonPrevolutions(): void { // TODO: This may cause funny business for double starters such as Pichu/Pikachu export const pokemonStarters: PokemonPrevolutions = {}; +/** + * The default species and all their evolutions + */ +export const defaultStarterSpeciesAndEvolutions: SpeciesId[] = defaultStarterSpecies.flatMap(id => { + const stage2ids = pokemonEvolutions[id]?.map(e => e.speciesId) ?? []; + const stage3ids = stage2ids.flatMap(s2id => pokemonEvolutions[s2id]?.map(e => e.speciesId) ?? []); + return [id, ...stage2ids, ...stage3ids]; +}); + export function initPokemonStarters(): void { const starterKeys = Object.keys(pokemonPrevolutions); starterKeys.forEach(pk => { diff --git a/src/data/balance/tms.ts b/src/data/balance/tms.ts index bd7cf401ad1..f7c330e3d95 100644 --- a/src/data/balance/tms.ts +++ b/src/data/balance/tms.ts @@ -68875,27 +68875,27 @@ interface TmPoolTiers { export const tmPoolTiers: TmPoolTiers = { [MoveId.MEGA_PUNCH]: ModifierTier.GREAT, - [MoveId.PAY_DAY]: ModifierTier.ULTRA, + [MoveId.PAY_DAY]: ModifierTier.COMMON, [MoveId.FIRE_PUNCH]: ModifierTier.GREAT, [MoveId.ICE_PUNCH]: ModifierTier.GREAT, [MoveId.THUNDER_PUNCH]: ModifierTier.GREAT, - [MoveId.SWORDS_DANCE]: ModifierTier.COMMON, + [MoveId.SWORDS_DANCE]: ModifierTier.GREAT, [MoveId.CUT]: ModifierTier.COMMON, - [MoveId.FLY]: ModifierTier.COMMON, + [MoveId.FLY]: ModifierTier.GREAT, [MoveId.MEGA_KICK]: ModifierTier.GREAT, [MoveId.BODY_SLAM]: ModifierTier.GREAT, [MoveId.TAKE_DOWN]: ModifierTier.GREAT, [MoveId.DOUBLE_EDGE]: ModifierTier.ULTRA, - [MoveId.PIN_MISSILE]: ModifierTier.COMMON, + [MoveId.PIN_MISSILE]: ModifierTier.GREAT, [MoveId.ROAR]: ModifierTier.COMMON, [MoveId.FLAMETHROWER]: ModifierTier.ULTRA, [MoveId.HYDRO_PUMP]: ModifierTier.ULTRA, [MoveId.SURF]: ModifierTier.ULTRA, [MoveId.ICE_BEAM]: ModifierTier.ULTRA, [MoveId.BLIZZARD]: ModifierTier.ULTRA, - [MoveId.PSYBEAM]: ModifierTier.GREAT, + [MoveId.PSYBEAM]: ModifierTier.COMMON, [MoveId.HYPER_BEAM]: ModifierTier.ULTRA, - [MoveId.LOW_KICK]: ModifierTier.COMMON, + [MoveId.LOW_KICK]: ModifierTier.GREAT, [MoveId.COUNTER]: ModifierTier.COMMON, [MoveId.STRENGTH]: ModifierTier.GREAT, [MoveId.SOLAR_BEAM]: ModifierTier.ULTRA, @@ -68907,9 +68907,9 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.DIG]: ModifierTier.GREAT, [MoveId.TOXIC]: ModifierTier.GREAT, [MoveId.PSYCHIC]: ModifierTier.ULTRA, - [MoveId.AGILITY]: ModifierTier.COMMON, + [MoveId.AGILITY]: ModifierTier.GREAT, [MoveId.NIGHT_SHADE]: ModifierTier.COMMON, - [MoveId.SCREECH]: ModifierTier.COMMON, + [MoveId.SCREECH]: ModifierTier.GREAT, [MoveId.DOUBLE_TEAM]: ModifierTier.COMMON, [MoveId.CONFUSE_RAY]: ModifierTier.COMMON, [MoveId.LIGHT_SCREEN]: ModifierTier.COMMON, @@ -68921,7 +68921,7 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.FIRE_BLAST]: ModifierTier.ULTRA, [MoveId.WATERFALL]: ModifierTier.GREAT, [MoveId.SWIFT]: ModifierTier.COMMON, - [MoveId.AMNESIA]: ModifierTier.COMMON, + [MoveId.AMNESIA]: ModifierTier.GREAT, [MoveId.DREAM_EATER]: ModifierTier.GREAT, [MoveId.LEECH_LIFE]: ModifierTier.ULTRA, [MoveId.FLASH]: ModifierTier.COMMON, @@ -68933,11 +68933,11 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.SUBSTITUTE]: ModifierTier.COMMON, [MoveId.THIEF]: ModifierTier.GREAT, [MoveId.SNORE]: ModifierTier.COMMON, - [MoveId.CURSE]: ModifierTier.COMMON, + [MoveId.CURSE]: ModifierTier.GREAT, [MoveId.REVERSAL]: ModifierTier.COMMON, [MoveId.SPITE]: ModifierTier.COMMON, [MoveId.PROTECT]: ModifierTier.COMMON, - [MoveId.SCARY_FACE]: ModifierTier.COMMON, + [MoveId.SCARY_FACE]: ModifierTier.GREAT, [MoveId.SLUDGE_BOMB]: ModifierTier.GREAT, [MoveId.MUD_SLAP]: ModifierTier.COMMON, [MoveId.SPIKES]: ModifierTier.COMMON, @@ -68979,8 +68979,8 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.TORMENT]: ModifierTier.COMMON, [MoveId.WILL_O_WISP]: ModifierTier.COMMON, [MoveId.FACADE]: ModifierTier.GREAT, - [MoveId.FOCUS_PUNCH]: ModifierTier.COMMON, - [MoveId.NATURE_POWER]: ModifierTier.COMMON, + [MoveId.FOCUS_PUNCH]: ModifierTier.GREAT, + [MoveId.NATURE_POWER]: ModifierTier.GREAT, [MoveId.CHARGE]: ModifierTier.COMMON, [MoveId.TAUNT]: ModifierTier.COMMON, [MoveId.HELPING_HAND]: ModifierTier.COMMON, @@ -68993,7 +68993,7 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.ENDEAVOR]: ModifierTier.COMMON, [MoveId.SKILL_SWAP]: ModifierTier.COMMON, [MoveId.IMPRISON]: ModifierTier.COMMON, - [MoveId.SECRET_POWER]: ModifierTier.COMMON, + [MoveId.SECRET_POWER]: ModifierTier.GREAT, [MoveId.DIVE]: ModifierTier.GREAT, [MoveId.FEATHER_DANCE]: ModifierTier.COMMON, [MoveId.BLAZE_KICK]: ModifierTier.GREAT, @@ -69001,12 +69001,12 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.BLAST_BURN]: ModifierTier.ULTRA, [MoveId.HYDRO_CANNON]: ModifierTier.ULTRA, [MoveId.WEATHER_BALL]: ModifierTier.COMMON, - [MoveId.FAKE_TEARS]: ModifierTier.COMMON, + [MoveId.FAKE_TEARS]: ModifierTier.GREAT, [MoveId.AIR_CUTTER]: ModifierTier.GREAT, [MoveId.OVERHEAT]: ModifierTier.ULTRA, [MoveId.ROCK_TOMB]: ModifierTier.GREAT, - [MoveId.METAL_SOUND]: ModifierTier.COMMON, - [MoveId.COSMIC_POWER]: ModifierTier.COMMON, + [MoveId.METAL_SOUND]: ModifierTier.GREAT, + [MoveId.COSMIC_POWER]: ModifierTier.GREAT, [MoveId.SIGNAL_BEAM]: ModifierTier.GREAT, [MoveId.SAND_TOMB]: ModifierTier.COMMON, [MoveId.MUDDY_WATER]: ModifierTier.GREAT, @@ -69016,10 +69016,10 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.IRON_DEFENSE]: ModifierTier.GREAT, [MoveId.DRAGON_CLAW]: ModifierTier.ULTRA, [MoveId.FRENZY_PLANT]: ModifierTier.ULTRA, - [MoveId.BULK_UP]: ModifierTier.COMMON, + [MoveId.BULK_UP]: ModifierTier.GREAT, [MoveId.BOUNCE]: ModifierTier.GREAT, [MoveId.MUD_SHOT]: ModifierTier.GREAT, - [MoveId.POISON_TAIL]: ModifierTier.GREAT, + [MoveId.POISON_TAIL]: ModifierTier.COMMON, [MoveId.COVET]: ModifierTier.GREAT, [MoveId.MAGICAL_LEAF]: ModifierTier.GREAT, [MoveId.CALM_MIND]: ModifierTier.GREAT, @@ -69047,7 +69047,7 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.TOXIC_SPIKES]: ModifierTier.GREAT, [MoveId.FLARE_BLITZ]: ModifierTier.ULTRA, [MoveId.AURA_SPHERE]: ModifierTier.GREAT, - [MoveId.ROCK_POLISH]: ModifierTier.COMMON, + [MoveId.ROCK_POLISH]: ModifierTier.GREAT, [MoveId.POISON_JAB]: ModifierTier.GREAT, [MoveId.DARK_PULSE]: ModifierTier.GREAT, [MoveId.AQUA_TAIL]: ModifierTier.GREAT, @@ -69063,8 +69063,8 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.ENERGY_BALL]: ModifierTier.GREAT, [MoveId.BRAVE_BIRD]: ModifierTier.ULTRA, [MoveId.EARTH_POWER]: ModifierTier.ULTRA, - [MoveId.GIGA_IMPACT]: ModifierTier.GREAT, - [MoveId.NASTY_PLOT]: ModifierTier.COMMON, + [MoveId.GIGA_IMPACT]: ModifierTier.ULTRA, + [MoveId.NASTY_PLOT]: ModifierTier.GREAT, [MoveId.AVALANCHE]: ModifierTier.GREAT, [MoveId.SHADOW_CLAW]: ModifierTier.GREAT, [MoveId.THUNDER_FANG]: ModifierTier.GREAT, @@ -69084,7 +69084,7 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.IRON_HEAD]: ModifierTier.GREAT, [MoveId.STONE_EDGE]: ModifierTier.ULTRA, [MoveId.STEALTH_ROCK]: ModifierTier.COMMON, - [MoveId.GRASS_KNOT]: ModifierTier.ULTRA, + [MoveId.GRASS_KNOT]: ModifierTier.GREAT, [MoveId.BUG_BITE]: ModifierTier.GREAT, [MoveId.CHARGE_BEAM]: ModifierTier.GREAT, [MoveId.HONE_CLAWS]: ModifierTier.COMMON, @@ -69102,7 +69102,7 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.FOUL_PLAY]: ModifierTier.ULTRA, [MoveId.ROUND]: ModifierTier.COMMON, [MoveId.ECHOED_VOICE]: ModifierTier.COMMON, - [MoveId.STORED_POWER]: ModifierTier.COMMON, + [MoveId.STORED_POWER]: ModifierTier.GREAT, [MoveId.ALLY_SWITCH]: ModifierTier.COMMON, [MoveId.SCALD]: ModifierTier.GREAT, [MoveId.HEX]: ModifierTier.GREAT, @@ -69130,7 +69130,7 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.SNARL]: ModifierTier.COMMON, [MoveId.PHANTOM_FORCE]: ModifierTier.ULTRA, [MoveId.PETAL_BLIZZARD]: ModifierTier.GREAT, - [MoveId.DISARMING_VOICE]: ModifierTier.GREAT, + [MoveId.DISARMING_VOICE]: ModifierTier.COMMON, [MoveId.DRAINING_KISS]: ModifierTier.GREAT, [MoveId.GRASSY_TERRAIN]: ModifierTier.COMMON, [MoveId.MISTY_TERRAIN]: ModifierTier.COMMON, @@ -69161,12 +69161,12 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.BREAKING_SWIPE]: ModifierTier.GREAT, [MoveId.STEEL_BEAM]: ModifierTier.ULTRA, [MoveId.EXPANDING_FORCE]: ModifierTier.GREAT, - [MoveId.STEEL_ROLLER]: ModifierTier.COMMON, + [MoveId.STEEL_ROLLER]: ModifierTier.GREAT, [MoveId.SCALE_SHOT]: ModifierTier.ULTRA, [MoveId.METEOR_BEAM]: ModifierTier.GREAT, - [MoveId.MISTY_EXPLOSION]: ModifierTier.COMMON, + [MoveId.MISTY_EXPLOSION]: ModifierTier.GREAT, [MoveId.GRASSY_GLIDE]: ModifierTier.COMMON, - [MoveId.RISING_VOLTAGE]: ModifierTier.COMMON, + [MoveId.RISING_VOLTAGE]: ModifierTier.GREAT, [MoveId.TERRAIN_PULSE]: ModifierTier.COMMON, [MoveId.SKITTER_SMACK]: ModifierTier.GREAT, [MoveId.BURNING_JEALOUSY]: ModifierTier.GREAT, @@ -69175,20 +69175,20 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.CORROSIVE_GAS]: ModifierTier.COMMON, [MoveId.COACHING]: ModifierTier.COMMON, [MoveId.FLIP_TURN]: ModifierTier.COMMON, - [MoveId.TRIPLE_AXEL]: ModifierTier.COMMON, - [MoveId.DUAL_WINGBEAT]: ModifierTier.COMMON, + [MoveId.TRIPLE_AXEL]: ModifierTier.ULTRA, + [MoveId.DUAL_WINGBEAT]: ModifierTier.GREAT, [MoveId.SCORCHING_SANDS]: ModifierTier.GREAT, [MoveId.TERA_BLAST]: ModifierTier.GREAT, [MoveId.ICE_SPINNER]: ModifierTier.GREAT, [MoveId.SNOWSCAPE]: ModifierTier.COMMON, [MoveId.POUNCE]: ModifierTier.COMMON, - [MoveId.TRAILBLAZE]: ModifierTier.COMMON, + [MoveId.TRAILBLAZE]: ModifierTier.GREAT, [MoveId.CHILLING_WATER]: ModifierTier.COMMON, [MoveId.HARD_PRESS]: ModifierTier.GREAT, [MoveId.DRAGON_CHEER]: ModifierTier.COMMON, [MoveId.ALLURING_VOICE]: ModifierTier.GREAT, [MoveId.TEMPER_FLARE]: ModifierTier.GREAT, - [MoveId.SUPERCELL_SLAM]: ModifierTier.GREAT, + [MoveId.SUPERCELL_SLAM]: ModifierTier.ULTRA, [MoveId.PSYCHIC_NOISE]: ModifierTier.GREAT, [MoveId.UPPER_HAND]: ModifierTier.COMMON, }; diff --git a/src/data/battle-anims.ts b/src/data/battle-anims.ts index aa4951f3263..5ff4472d148 100644 --- a/src/data/battle-anims.ts +++ b/src/data/battle-anims.ts @@ -291,9 +291,17 @@ class AnimTimedSoundEvent extends AnimTimedEvent { } catch (err) { console.error(err); } - return Math.ceil((globalScene.sound.get(`battle_anims/${this.resourceName}`).totalDuration * 1000) / 33.33); + const sound = globalScene.sound.get(`battle_anims/${this.resourceName}`); + if (!sound) { + return 0; + } + return Math.ceil((sound.totalDuration * 1000) / 33.33); } - return Math.ceil((battleAnim.user!.cry(soundConfig).totalDuration * 1000) / 33.33); // TODO: is the bang behind user correct? + const cry = battleAnim.user!.cry(soundConfig); // TODO: is the bang behind user correct? + if (!cry) { + return 0; + } + return Math.ceil((cry.totalDuration * 1000) / 33.33); } getEventType(): string { diff --git a/src/data/battler-tags.ts b/src/data/battler-tags.ts index 104eca0e407..5484eba7271 100644 --- a/src/data/battler-tags.ts +++ b/src/data/battler-tags.ts @@ -34,7 +34,7 @@ import type { StatStageChangeCallback } from "#phases/stat-stage-change-phase"; import i18next from "#plugins/i18n"; import type { AbilityBattlerTagType, - BattlerTagTypeData, + BattlerTagData, ContactSetStatusProtectedTagType, ContactStatStageChangeProtectedTagType, CritStageBoostTagType, @@ -228,26 +228,27 @@ interface GenericSerializableBattlerTag extends Serial * Descendants can override {@linkcode isMoveRestricted} to restrict moves that * match a condition. A restricted move gets cancelled before it is used. * Players and enemies should not be allowed to select restricted moves. + * @todo Require descendant subclasses to inherit a `PRE_MOVE` lapse type */ export abstract class MoveRestrictionBattlerTag extends SerializableBattlerTag { public declare readonly tagType: MoveRestrictionBattlerTagType; override lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { - if (lapseType === BattlerTagLapseType.PRE_MOVE) { - // Cancel the affected pokemon's selected move - const phase = globalScene.phaseManager.getCurrentPhase() as MovePhase; - const move = phase.move; - - if (this.isMoveRestricted(move.moveId, pokemon)) { - if (this.interruptedText(pokemon, move.moveId)) { - globalScene.phaseManager.queueMessage(this.interruptedText(pokemon, move.moveId)); - } - phase.cancel(); - } - - return true; + if (lapseType !== BattlerTagLapseType.PRE_MOVE) { + return super.lapse(pokemon, lapseType); } - return super.lapse(pokemon, lapseType); + // Cancel the affected pokemon's selected move + const phase = globalScene.phaseManager.getCurrentPhase() as MovePhase; + const move = phase.move; + + if (this.isMoveRestricted(move.moveId, pokemon)) { + if (this.interruptedText(pokemon, move.moveId)) { + globalScene.phaseManager.queueMessage(this.interruptedText(pokemon, move.moveId)); + } + phase.cancel(); + } + + return true; } /** @@ -1058,8 +1059,7 @@ export class SeedTag extends SerializableBattlerTag { // Check which opponent to restore HP to const source = pokemon.getOpponents().find(o => o.getBattlerIndex() === this.sourceIndex); if (!source) { - console.warn(`Failed to get source Pokemon for SeedTag lapse; id: ${this.sourceId}`); - return false; + return true; } const cancelled = new BooleanHolder(false); @@ -3843,7 +3843,7 @@ export function getBattlerTag( * @param source - An object containing the data necessary to reconstruct the BattlerTag. * @returns The valid battler tag */ -export function loadBattlerTag(source: BattlerTag | BattlerTagTypeData): BattlerTag { +export function loadBattlerTag(source: BattlerTag | BattlerTagData): BattlerTag { // TODO: Remove this bang by fixing the signature of `getBattlerTag` // to allow undefined sourceIds and sourceMoves (with appropriate fallback for tags that require it) const tag = getBattlerTag(source.tagType, source.turnCount, source.sourceMove!, source.sourceId!); diff --git a/src/data/challenge.ts b/src/data/challenge.ts index 3c282e7640e..cea8661e78c 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -1,6 +1,6 @@ import type { FixedBattleConfig } from "#app/battle"; import { getRandomTrainerFunc } from "#app/battle"; -import { defaultStarterSpeciesAndEvolutions } from "#app/constants"; +import { defaultStarterSpeciesAndEvolutions } from "#balance/pokemon-evolutions"; import { speciesStarterCosts } from "#balance/starters"; import type { PokemonSpecies } from "#data/pokemon-species"; import { AbilityAttr } from "#enums/ability-attr"; @@ -27,7 +27,7 @@ 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"; -import { toCamelCase, toSnakeCase } from "#utils/strings"; +import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; /** A constant for the default max cost of the starting party before a run */ @@ -764,7 +764,7 @@ export class SingleTypeChallenge extends Challenge { } getValue(overrideValue: number = this.value): string { - return toSnakeCase(PokemonType[overrideValue - 1]); + return i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[overrideValue - 1])}`); } getDescription(overrideValue: number = this.value): string { diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 563e87ef07d..392be028dd8 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -93,6 +93,7 @@ import { getEnumValues } from "#utils/enums"; import { toCamelCase, toTitleCase } from "#utils/strings"; import i18next from "i18next"; import { applyChallenges } from "#utils/challenge-utils"; +import type { AbstractConstructor } from "#types/type-helpers"; /** * A function used to conditionally determine execution of a given {@linkcode MoveAttr}. @@ -1055,16 +1056,11 @@ export class SelfStatusMove extends Move { } } -// TODO: Figure out how to improve the signature of this so that -// the `ChargeMove` function knows that the argument `Base` is a specific subclass of move that cannot -// be abstract. -// Right now, I only know how to do this by using the type conjunction (the & operators) -type SubMove = new (...args: any[]) => Move & { - is(moveKind: K): this is MoveClassMap[K]; -}; +type SubMove = AbstractConstructor function ChargeMove(Base: TBase, nameAppend: string) { - return class extends Base { + // NB: This cannot be made into a oneline return + abstract class Charging extends Base { /** The animation to play during the move's charging phase */ public readonly chargeAnim: ChargeAnim = ChargeAnim[`${MoveId[this.id]}_CHARGING`]; /** The message to show during the move's charging phase */ @@ -1141,6 +1137,7 @@ function ChargeMove(Base: TBase, nameAppend: string) { return this; } }; + return Charging; } export class ChargingAttackMove extends ChargeMove(AttackMove, "ChargingAttackMove") {} @@ -2325,6 +2322,13 @@ export class HealOnAllyAttr extends HealAttr { // Don't trigger if not targeting an ally return target === user.getAlly() && super.canApply(user, target, _move, _args); } + + override apply(user: Pokemon, target: Pokemon, _move: Move, _args: any[]): boolean { + if (user.isOpponent(target)) { + return false; + } + return super.apply(user, target, _move, _args); + } } /** @@ -3270,7 +3274,6 @@ export class DelayedAttackAttr extends OverrideMoveEffectAttr { ) ) - user.pushMoveHistory({move: move.id, targets: [target.getBattlerIndex()], result: MoveResult.OTHER, useMode, turn: globalScene.currentBattle.turn}) user.pushMoveHistory({move: move.id, targets: [target.getBattlerIndex()], result: MoveResult.OTHER, useMode, turn: globalScene.currentBattle.turn}) // Queue up an attack on the given slot. globalScene.arena.positionalTagManager.addTag({ @@ -6862,12 +6865,15 @@ export class CopyBiomeTypeAttr extends MoveEffectAttr { } } +/** + * Attribute to override the target's current types to the given type. + * Used by {@linkcode MoveId.SOAK} and {@linkcode MoveId.MAGIC_POWDER}. + */ export class ChangeTypeAttr extends MoveEffectAttr { private type: PokemonType; constructor(type: PokemonType) { super(false); - this.type = type; } @@ -6875,7 +6881,7 @@ export class ChangeTypeAttr extends MoveEffectAttr { target.summonData.types = [ this.type ]; target.updateInfo(); - globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(target), typeName: i18next.t(`pokemonInfo:Type.${PokemonType[this.type]}`) })); + globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:transformedIntoType", { pokemonName: getPokemonNameWithAffix(target), typeName: i18next.t(`pokemonInfo:type.${toCamelCase(PokemonType[this.type])}`) })); return true; } @@ -8900,7 +8906,9 @@ export function initMoves() { .attr(AddArenaTagAttr, ArenaTagType.REFLECT, 5, true) .target(MoveTarget.USER_SIDE), new SelfStatusMove(MoveId.FOCUS_ENERGY, PokemonType.NORMAL, -1, 30, -1, 0, 1) - .attr(AddBattlerTagAttr, BattlerTagType.CRIT_BOOST, true, true), + .attr(AddBattlerTagAttr, BattlerTagType.CRIT_BOOST, true, true) + // TODO: Remove once dragon cheer & focus energy are merged into 1 tag + .condition((_user, target) => !target.getTag(BattlerTagType.DRAGON_CHEER)), new AttackMove(MoveId.BIDE, PokemonType.NORMAL, MoveCategory.PHYSICAL, -1, -1, 10, -1, 1, 1) .target(MoveTarget.USER) .unimplemented(), @@ -9427,7 +9435,9 @@ export function initMoves() { .attr(AddBattlerTagAttr, BattlerTagType.HELPING_HAND) .ignoresSubstitute() .target(MoveTarget.NEAR_ALLY) - .condition(failIfSingleBattle), + .condition(failIfSingleBattle) + // should stack multiplicatively if used multiple times in 1 turn + .edgeCase(), new StatusMove(MoveId.TRICK, PokemonType.PSYCHIC, 100, 10, -1, 0, 3) .unimplemented(), new StatusMove(MoveId.ROLE_PLAY, PokemonType.PSYCHIC, -1, 10, -1, 0, 3) @@ -11595,6 +11605,8 @@ export function initMoves() { .attr(OpponentHighHpPowerAttr, 100), new StatusMove(MoveId.DRAGON_CHEER, PokemonType.DRAGON, -1, 15, -1, 0, 9) .attr(AddBattlerTagAttr, BattlerTagType.DRAGON_CHEER, false, true) + // TODO: Remove once dragon cheer & focus energy are merged into 1 tag + .condition((_user, target) => !target.getTag(BattlerTagType.CRIT_BOOST)) .target(MoveTarget.NEAR_ALLY), new AttackMove(MoveId.ALLURING_VOICE, PokemonType.FAIRY, MoveCategory.SPECIAL, 80, 100, 10, 100, 0, 9) .attr(AddBattlerTagIfBoostedAttr, BattlerTagType.CONFUSED) diff --git a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts index 196ca873f4e..358bba92a09 100644 --- a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts +++ b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts @@ -237,7 +237,7 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder. const config = globalScene.currentBattle.mysteryEncounter!.enemyPartyConfigs[0]; config.pokemonConfigs![0].tags = [BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON]; config.pokemonConfigs![0].mysteryEncounterBattleEffects = (pokemon: Pokemon) => { - queueEncounterMessage(`${namespace}:option.2.boss_enraged`); + queueEncounterMessage(`${namespace}:option.2.bossEnraged`); globalScene.phaseManager.unshiftNew( "StatStageChangePhase", pokemon.getBattlerIndex(), diff --git a/src/data/mystery-encounters/encounters/training-session-encounter.ts b/src/data/mystery-encounters/encounters/training-session-encounter.ts index b8173aa5fed..02e7a5c5575 100644 --- a/src/data/mystery-encounters/encounters/training-session-encounter.ts +++ b/src/data/mystery-encounters/encounters/training-session-encounter.ts @@ -188,7 +188,7 @@ export const TrainingSessionEncounter: MysteryEncounter = MysteryEncounterBuilde // Return the options for nature selection return getEnumValues(Nature).map((nature: Nature) => { const option: OptionSelectItem = { - label: getNatureName(nature, true, true, true, globalScene.uiTheme), + label: getNatureName(nature, true, true, true), handler: () => { // Pokemon and second option selected encounter.setDialogueToken("nature", getNatureName(nature)); 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 af576ffd8be..ed588ea2884 100644 --- a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts +++ b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts @@ -249,7 +249,7 @@ async function tryApplyDigRewardItems() { await showEncounterText( i18next.t("battle:rewardGainCount", { modifierName: leftovers.name, - count: 2, + count: 1, }), null, undefined, diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index 790bdf0dbef..240a0df9e95 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -2,6 +2,7 @@ import { globalScene } from "#app/global-scene"; import { allSpecies, modifierTypes } from "#data/data-lists"; import { getLevelTotalExp } from "#data/exp"; import type { PokemonSpecies } from "#data/pokemon-species"; +import { AbilityId } from "#enums/ability-id"; import { Challenges } from "#enums/challenges"; import { ModifierTier } from "#enums/modifier-tier"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; @@ -10,8 +11,9 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { Nature } from "#enums/nature"; import { PartyMemberStrength } from "#enums/party-member-strength"; import { PlayerGender } from "#enums/player-gender"; -import { PokemonType } from "#enums/pokemon-type"; +import { MAX_POKEMON_TYPE, PokemonType } from "#enums/pokemon-type"; import { SpeciesId } from "#enums/species-id"; +import { StatusEffect } from "#enums/status-effect"; import { TrainerType } from "#enums/trainer-type"; import type { PlayerPokemon, Pokemon } from "#field/pokemon"; import type { PokemonHeldItemModifier } from "#modifiers/modifier"; @@ -219,6 +221,7 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit await showEncounterText(`${namespace}:option.1.dreamComplete`); await doNewTeamPostProcess(transformations); + globalScene.phaseManager.unshiftNew("PartyHealPhase", true); setEncounterRewards({ guaranteedModifierTypeFuncs: [ modifierTypes.MEMORY_MUSHROOM, @@ -230,7 +233,7 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit ], fillRemaining: false, }); - leaveEncounterWithoutBattle(true); + leaveEncounterWithoutBattle(false); }) .build(), ) @@ -431,6 +434,8 @@ function getTeamTransformations(): PokemonTransformation[] { newAbilityIndex, undefined, ); + + transformation.newPokemon.teraType = randSeedInt(MAX_POKEMON_TYPE); } return pokemonTransformations; @@ -440,6 +445,8 @@ async function doNewTeamPostProcess(transformations: PokemonTransformation[]) { let atLeastOneNewStarter = false; for (const transformation of transformations) { const previousPokemon = transformation.previousPokemon; + const oldHpRatio = previousPokemon.getHpRatio(true); + const oldStatus = previousPokemon.status; const newPokemon = transformation.newPokemon; const speciesRootForm = newPokemon.species.getRootSpeciesId(); @@ -462,6 +469,19 @@ async function doNewTeamPostProcess(transformations: PokemonTransformation[]) { } newPokemon.calculateStats(); + if (oldHpRatio > 0) { + newPokemon.hp = Math.ceil(oldHpRatio * newPokemon.getMaxHp()); + // Assume that the `status` instance can always safely be transferred to the new pokemon + // This is the case (as of version 1.10.4) + // Safeguard against COMATOSE here + if (!newPokemon.hasAbility(AbilityId.COMATOSE, false, true)) { + newPokemon.status = oldStatus; + } + } else { + newPokemon.hp = 0; + newPokemon.doSetStatus(StatusEffect.FAINT); + } + await newPokemon.updateInfo(); } diff --git a/src/data/mystery-encounters/utils/encounter-dialogue-utils.ts b/src/data/mystery-encounters/utils/encounter-dialogue-utils.ts index 54179ee2604..1a9b008f9e9 100644 --- a/src/data/mystery-encounters/utils/encounter-dialogue-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-dialogue-utils.ts @@ -1,6 +1,5 @@ import { globalScene } from "#app/global-scene"; import type { TextStyle } from "#enums/text-style"; -import { UiTheme } from "#enums/ui-theme"; import { getTextWithColors } from "#ui/text"; import { isNullOrUndefined } from "#utils/common"; import i18next from "i18next"; @@ -16,14 +15,12 @@ export function getEncounterText(keyOrString?: string, primaryStyle?: TextStyle) return null; } - const uiTheme = globalScene.uiTheme ?? UiTheme.DEFAULT; - let textString: string | null = getTextWithDialogueTokens(keyOrString); // Can only color the text if a Primary Style is defined // primaryStyle is applied to all text that does not have its own specified style if (primaryStyle && textString) { - textString = getTextWithColors(textString, primaryStyle, uiTheme, true); + textString = getTextWithColors(textString, primaryStyle, true); } return textString; diff --git a/src/data/nature.ts b/src/data/nature.ts index 65e401cd288..116732d60b3 100644 --- a/src/data/nature.ts +++ b/src/data/nature.ts @@ -1,7 +1,6 @@ import { Nature } from "#enums/nature"; 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 { toCamelCase } from "#utils/strings"; import i18next from "i18next"; @@ -11,7 +10,6 @@ export function getNatureName( includeStatEffects = false, forStarterSelect = false, ignoreBBCode = false, - uiTheme: UiTheme = UiTheme.DEFAULT, ): string { let ret = toCamelCase(Nature[nature]); //Translating nature @@ -31,7 +29,7 @@ export function getNatureName( } const textStyle = forStarterSelect ? TextStyle.SUMMARY_ALT : TextStyle.WINDOW; const getTextFrag = !ignoreBBCode - ? (text: string, style: TextStyle) => getBBCodeFrag(text, style, uiTheme) + ? (text: string, style: TextStyle) => getBBCodeFrag(text, style) : (text: string, _style: TextStyle) => text; if (increasedStat && decreasedStat) { ret = `${getTextFrag(`${ret}${!forStarterSelect ? "\n" : " "}(`, textStyle)}${getTextFrag(`+${i18next.t(getShortenedStatKey(increasedStat))}`, TextStyle.SUMMARY_PINK)}${getTextFrag("/", textStyle)}${getTextFrag(`-${i18next.t(getShortenedStatKey(decreasedStat))}`, TextStyle.SUMMARY_BLUE)}${getTextFrag(")", textStyle)}`; diff --git a/src/data/phase-priority-queue.ts b/src/data/phase-priority-queue.ts index 88361b0f4fa..012344d59f6 100644 --- a/src/data/phase-priority-queue.ts +++ b/src/data/phase-priority-queue.ts @@ -44,6 +44,34 @@ export abstract class PhasePriorityQueue { public clear(): void { this.queue.splice(0, this.queue.length); } + + /** + * Attempt to remove one or more Phases from the current queue. + * @param phaseFilter - The function to select phases for removal + * @param removeCount - The maximum number of phases to remove, or `all` to remove all matching phases; + * default `1` + * @returns The number of successfully removed phases + * @todo Remove this eventually once the patchwork bug this is used for is fixed + */ + public tryRemovePhase(phaseFilter: (phase: Phase) => boolean, removeCount: number | "all" = 1): number { + if (removeCount === "all") { + removeCount = this.queue.length; + } else if (removeCount < 1) { + return 0; + } + let numRemoved = 0; + + do { + const phaseIndex = this.queue.findIndex(phaseFilter); + if (phaseIndex === -1) { + break; + } + this.queue.splice(phaseIndex, 1); + numRemoved++; + } while (numRemoved < removeCount && this.queue.length > 0); + + return numRemoved; + } } /** diff --git a/src/data/pokemon-species.ts b/src/data/pokemon-species.ts index 064ad57cfb3..d5049569e61 100644 --- a/src/data/pokemon-species.ts +++ b/src/data/pokemon-species.ts @@ -593,14 +593,14 @@ export abstract class PokemonSpeciesForm { }); } - cry(soundConfig?: Phaser.Types.Sound.SoundConfig, ignorePlay?: boolean): AnySound { + cry(soundConfig?: Phaser.Types.Sound.SoundConfig, ignorePlay?: boolean): AnySound | null { const cryKey = this.getCryKey(this.formIndex); let cry: AnySound | null = globalScene.sound.get(cryKey) as AnySound; if (cry?.pendingRemove) { cry = null; } cry = globalScene.playSound(cry ?? cryKey, soundConfig); - if (ignorePlay) { + if (cry && ignorePlay) { cry.stop(); } return cry; @@ -795,7 +795,7 @@ export class PokemonSpecies extends PokemonSpeciesForm implements Localizable { return Gender.GENDERLESS; } - if (randSeedFloat() <= this.malePercent) { + if (randSeedFloat() * 100 <= this.malePercent) { return Gender.MALE; } return Gender.FEMALE; diff --git a/src/data/pokemon/pokemon-data.ts b/src/data/pokemon/pokemon-data.ts index 0bd6af0bb04..87ffbbab4cd 100644 --- a/src/data/pokemon/pokemon-data.ts +++ b/src/data/pokemon/pokemon-data.ts @@ -11,6 +11,7 @@ import type { MoveId } from "#enums/move-id"; import type { Nature } from "#enums/nature"; import type { PokemonType } from "#enums/pokemon-type"; import type { SpeciesId } from "#enums/species-id"; +import { StatusEffect } from "#enums/status-effect"; import type { AttackMoveResult } from "#types/attack-move-result"; import type { IllusionData } from "#types/illusion-data"; import type { TurnMove } from "#types/turn-move"; @@ -326,6 +327,14 @@ export class PokemonTurnData { public switchedInThisTurn = false; public failedRunAway = false; public joinedRound = false; + /** Tracker for a pending status effect + * + * @remarks + * Set whenever {@linkcode Pokemon#trySetStatus} succeeds in order to prevent subsequent status effects + * from being applied. Necessary because the status is not actually set until the {@linkcode ObtainStatusEffectPhase} runs, + * which may not happen before another status effect is attempted to be applied. + */ + public pendingStatus: StatusEffect = StatusEffect.NONE; /** * The amount of times this Pokemon has acted again and used a move in the current turn. * Used to make sure multi-hits occur properly when the user is diff --git a/src/enums/pokemon-type.ts b/src/enums/pokemon-type.ts index 08ccd6772d4..034bf81c33f 100644 --- a/src/enums/pokemon-type.ts +++ b/src/enums/pokemon-type.ts @@ -21,3 +21,6 @@ export enum PokemonType { FAIRY, STELLAR } + +/** The largest legal value for a {@linkcode PokemonType} (includes Stellar) */ +export const MAX_POKEMON_TYPE = PokemonType.STELLAR; \ No newline at end of file diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 4af90c994c3..65ffd223fa5 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -487,7 +487,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { getNameToRender(useIllusion = true) { const illusion = this.summonData.illusion; const name = useIllusion ? (illusion?.name ?? this.name) : this.name; - const nickname: string | undefined = useIllusion ? illusion?.nickname : this.nickname; + const nickname: string | undefined = useIllusion ? (illusion?.nickname ?? this.nickname) : this.nickname; try { if (nickname) { return decodeURIComponent(escape(atob(nickname))); // TODO: Remove `atob` and `escape`... eventually... @@ -1285,7 +1285,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { } // During the Pokemon's MoveEffect phase, the offset is removed to put the Pokemon "in focus" const currentPhase = globalScene.phaseManager.getCurrentPhase(); - return !(currentPhase?.is("MoveEffectPhase") && currentPhase.getPokemon() === this); + return !(currentPhase.is("MoveEffectPhase") && currentPhase.getPokemon() === this); } /** If this Pokemon has a Substitute on the field, removes its sprite from the field. */ @@ -1801,7 +1801,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { * @returns Whether this Pokemon is currently fused with another species. */ isFusion(useIllusion = false): boolean { - return useIllusion ? !!this.summonData.illusion?.fusionSpecies : !!this.fusionSpecies; + return !!(useIllusion ? (this.summonData.illusion?.fusionSpecies ?? this.fusionSpecies) : this.fusionSpecies); } /** @@ -2254,8 +2254,16 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { return this.hasPassive() && (!canApply || this.canApplyAbility(true)) && this.getPassiveAbility().hasAttr(attrType); } - public getAbilityPriorities(): [number, number] { - return [this.getAbility().postSummonPriority, this.getPassiveAbility().postSummonPriority]; + /** + * Return the ability priorities of the pokemon's ability and, if enabled, its passive ability + * @returns A tuple containing the ability priorities of the pokemon + */ + public getAbilityPriorities(): [number] | [activePriority: number, passivePriority: number] { + const abilityPriority = this.getAbility().postSummonPriority; + if (this.hasPassive()) { + return [abilityPriority, this.getPassiveAbility().postSummonPriority]; + } + return [abilityPriority]; } /** @@ -3129,14 +3137,17 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { if (this.level < levelMove[0]) { break; } - let weight = levelMove[0]; + let weight = levelMove[0] + 20; // Evolution Moves - if (weight === EVOLVE_MOVE) { - weight = 50; + if (levelMove[0] === EVOLVE_MOVE) { + weight = 70; } // Assume level 1 moves with 80+ BP are "move reminder" moves and bump their weight. Trainers use actual relearn moves. - if ((weight === 1 && allMoves[levelMove[1]].power >= 80) || (weight === RELEARN_MOVE && this.hasTrainer())) { - weight = 40; + if ( + (levelMove[0] === 1 && allMoves[levelMove[1]].power >= 80) || + (levelMove[0] === RELEARN_MOVE && this.hasTrainer()) + ) { + weight = 60; } if (!movePool.some(m => m[0] === levelMove[1]) && !allMoves[levelMove[1]].name.endsWith(" (N)")) { movePool.push([levelMove[1], weight]); @@ -3166,11 +3177,11 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { } if (compatible && !movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(" (N)")) { if (tmPoolTiers[moveId] === ModifierTier.COMMON && this.level >= 15) { - movePool.push([moveId, 4]); + movePool.push([moveId, 24]); } else if (tmPoolTiers[moveId] === ModifierTier.GREAT && this.level >= 30) { - movePool.push([moveId, 8]); + movePool.push([moveId, 28]); } else if (tmPoolTiers[moveId] === ModifierTier.ULTRA && this.level >= 50) { - movePool.push([moveId, 14]); + movePool.push([moveId, 34]); } } } @@ -3180,7 +3191,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { for (let i = 0; i < 3; i++) { const moveId = speciesEggMoves[this.species.getRootSpeciesId()][i]; if (!movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(" (N)")) { - movePool.push([moveId, 40]); + movePool.push([moveId, 60]); } } const moveId = speciesEggMoves[this.species.getRootSpeciesId()][3]; @@ -3191,13 +3202,13 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { !allMoves[moveId].name.endsWith(" (N)") && !this.isBoss() ) { - movePool.push([moveId, 30]); + movePool.push([moveId, 50]); } if (this.fusionSpecies) { for (let i = 0; i < 3; i++) { const moveId = speciesEggMoves[this.fusionSpecies.getRootSpeciesId()][i]; if (!movePool.some(m => m[0] === moveId) && !allMoves[moveId].name.endsWith(" (N)")) { - movePool.push([moveId, 40]); + movePool.push([moveId, 60]); } } const moveId = speciesEggMoves[this.fusionSpecies.getRootSpeciesId()][3]; @@ -3208,7 +3219,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { !allMoves[moveId].name.endsWith(" (N)") && !this.isBoss() ) { - movePool.push([moveId, 30]); + movePool.push([moveId, 50]); } } } @@ -3289,6 +3300,18 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { rand -= stabMovePool[index++][1]; } this.moveset.push(new PokemonMove(stabMovePool[index][0])); + } else { + // If there are no damaging STAB moves, just force a random damaging move + const attackMovePool = baseWeights.filter(m => allMoves[m[0]].category !== MoveCategory.STATUS); + if (attackMovePool.length) { + const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0); + let rand = randSeedInt(totalWeight); + let index = 0; + while (rand > attackMovePool[index][1]) { + rand -= attackMovePool[index++][1]; + } + this.moveset.push(new PokemonMove(attackMovePool[index][0], 0, 0)); + } } while (baseWeights.length > this.moveset.length && this.moveset.length < 4) { @@ -4585,28 +4608,36 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { }); } - cry(soundConfig?: Phaser.Types.Sound.SoundConfig, sceneOverride?: BattleScene): AnySound { + cry(soundConfig?: Phaser.Types.Sound.SoundConfig, sceneOverride?: BattleScene): AnySound | null { const scene = sceneOverride ?? globalScene; // TODO: is `sceneOverride` needed? const cry = this.getSpeciesForm(undefined, true).cry(soundConfig); + if (!cry) { + return cry; + } let duration = cry.totalDuration * 1000; if (this.fusionSpecies && this.getSpeciesForm(undefined, true) !== this.getFusionSpeciesForm(undefined, true)) { - let fusionCry = this.getFusionSpeciesForm(undefined, true).cry(soundConfig, true); + const fusionCry = this.getFusionSpeciesForm(undefined, true).cry(soundConfig, true); + if (!fusionCry) { + return cry; + } duration = Math.min(duration, fusionCry.totalDuration * 1000); fusionCry.destroy(); scene.time.delayedCall(fixedInt(Math.ceil(duration * 0.4)), () => { try { SoundFade.fadeOut(scene, cry, fixedInt(Math.ceil(duration * 0.2))); - fusionCry = this.getFusionSpeciesForm(undefined, true).cry({ + const fusionCryInner = this.getFusionSpeciesForm(undefined, true).cry({ seek: Math.max(fusionCry.totalDuration * 0.4, 0), ...soundConfig, }); - SoundFade.fadeIn( - scene, - fusionCry, - fixedInt(Math.ceil(duration * 0.2)), - scene.masterVolume * scene.fieldVolume, - 0, - ); + if (fusionCryInner) { + SoundFade.fadeIn( + scene, + fusionCryInner, + fixedInt(Math.ceil(duration * 0.2)), + scene.masterVolume * scene.fieldVolume, + 0, + ); + } } catch (err) { console.error(err); } @@ -4634,14 +4665,14 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { crySoundConfig.rate = 0.7; } } - const cry = globalScene.playSound(key, crySoundConfig) as AnySound; + const cry = globalScene.playSound(key, crySoundConfig); if (!cry || globalScene.fieldVolume === 0) { callback(); return; } const sprite = this.getSprite(); const tintSprite = this.getTintSprite(); - const delay = Math.max(globalScene.sound.get(key).totalDuration * 50, 25); + const delay = Math.max(cry.totalDuration * 50, 25); let frameProgress = 0; let frameThreshold: number; @@ -4694,20 +4725,20 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { const key = this.species.getCryKey(this.formIndex); let i = 0; let rate = 0.85; - const cry = globalScene.playSound(key, { rate: rate }) as AnySound; + const cry = globalScene.playSound(key, { rate: rate }); const sprite = this.getSprite(); const tintSprite = this.getTintSprite(); - let duration = cry.totalDuration * 1000; const fusionCryKey = this.fusionSpecies!.getCryKey(this.fusionFormIndex); let fusionCry = globalScene.playSound(fusionCryKey, { rate: rate, - }) as AnySound; + }); if (!cry || !fusionCry || globalScene.fieldVolume === 0) { callback(); return; } fusionCry.stop(); + let duration = cry.totalDuration * 1000; duration = Math.min(duration, fusionCry.totalDuration * 1000); fusionCry.destroy(); const delay = Math.max(duration * 0.05, 25); @@ -4750,16 +4781,20 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { if (i === transitionIndex && fusionCryKey) { SoundFade.fadeOut(globalScene, cry, fixedInt(Math.ceil((duration / rate) * 0.2))); fusionCry = globalScene.playSound(fusionCryKey, { - seek: Math.max(fusionCry.totalDuration * 0.4, 0), + // TODO: This bang is correct as this callback can only be called once, but + // this whole block with conditionally reassigning fusionCry needs a second lock. + seek: Math.max(fusionCry!.totalDuration * 0.4, 0), rate: rate, }); - SoundFade.fadeIn( - globalScene, - fusionCry, - fixedInt(Math.ceil((duration / rate) * 0.2)), - globalScene.masterVolume * globalScene.fieldVolume, - 0, - ); + if (fusionCry) { + SoundFade.fadeIn( + globalScene, + fusionCry, + fixedInt(Math.ceil((duration / rate) * 0.2)), + globalScene.masterVolume * globalScene.fieldVolume, + 0, + ); + } } rate *= 0.99; if (cry && !cry.pendingRemove) { @@ -4861,7 +4896,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { 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) { + if (overrideStatus ? this.status?.effect === effect : this.status || this.turnData.pendingStatus) { this.queueStatusImmuneMessage(quiet, overrideStatus ? "overlap" : "other"); // having different status displays generic fail message return false; } @@ -5005,7 +5040,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { */ if (effect === StatusEffect.SLEEP || effect === StatusEffect.FREEZE) { const currentPhase = globalScene.phaseManager.getCurrentPhase(); - if (currentPhase?.is("MoveEffectPhase") && currentPhase.getUserPokemon() === this) { + if (currentPhase.is("MoveEffectPhase") && currentPhase.getUserPokemon() === this) { this.turnData.hitCount = 1; this.turnData.hitsLeft = 1; } @@ -5013,6 +5048,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { if (overrideStatus) { this.resetStatus(false); + } else { + this.turnData.pendingStatus = effect; } globalScene.phaseManager.unshiftNew( @@ -5032,6 +5069,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { * Set this Pokemon's {@linkcode status | non-volatile status condition} to the specified effect. * @param effect - The {@linkcode StatusEffect} to set * @remarks + * Clears this pokemon's `pendingStatus` in its {@linkcode Pokemon.turnData | turnData}. + * * ⚠️ This method does **not** check for feasibility; that is the responsibility of the caller. */ doSetStatus(effect: Exclude): void; @@ -5040,6 +5079,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { * @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 + * Clears this pokemon's `pendingStatus` in its {@linkcode Pokemon#turnData}. + * * ⚠️ This method does **not** check for feasibility; that is the responsibility of the caller. */ doSetStatus(effect: StatusEffect.SLEEP, sleepTurnsRemaining?: number): void; @@ -5049,6 +5090,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { * @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 + * Clears this pokemon's `pendingStatus` in its {@linkcode Pokemon#turnData}. + * * ⚠️ This method does **not** check for feasibility; that is the responsibility of the caller. */ doSetStatus(effect: StatusEffect, sleepTurnsRemaining?: number): void; @@ -5058,6 +5101,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { * @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 + * Clears this pokemon's `pendingStatus` in its {@linkcode Pokemon#turnData}. + * * ⚠️ 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 */ @@ -5065,6 +5110,8 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { effect: StatusEffect, sleepTurnsRemaining = effect !== StatusEffect.SLEEP ? 0 : this.randBattleSeedIntRange(2, 4), ): void { + // Reset any pending status + this.turnData.pendingStatus = StatusEffect.NONE; switch (effect) { case StatusEffect.POISON: case StatusEffect.TOXIC: @@ -6942,7 +6989,7 @@ export class EnemyPokemon extends Pokemon { const leftoverStats = EFFECTIVE_STATS.filter((s: EffectiveStat) => this.getStatStage(s) < 6); const statWeights = leftoverStats.map((s: EffectiveStat) => this.getStat(s, false)); - let boostedStat: EffectiveStat; + let boostedStat: EffectiveStat | undefined; const statThresholds: number[] = []; let totalWeight = 0; @@ -6960,6 +7007,11 @@ export class EnemyPokemon extends Pokemon { } } + if (boostedStat === undefined) { + this.bossSegmentIndex--; + return; + } + let stages = 1; // increase the boost if the boss has at least 3 segments and we passed last shield @@ -6975,7 +7027,7 @@ export class EnemyPokemon extends Pokemon { "StatStageChangePhase", this.getBattlerIndex(), true, - [boostedStat!], + [boostedStat], stages, true, true, diff --git a/src/field/trainer.ts b/src/field/trainer.ts index acbc8031dbc..6d427585a87 100644 --- a/src/field/trainer.ts +++ b/src/field/trainer.ts @@ -17,7 +17,7 @@ import { getIsInitialized, initI18n } from "#plugins/i18n"; import type { TrainerConfig } from "#trainers/trainer-config"; import { trainerConfigs } from "#trainers/trainer-config"; import { TrainerPartyCompoundTemplate, type TrainerPartyTemplate } from "#trainers/trainer-party-template"; -import { randSeedInt, randSeedItem, randSeedWeightedItem } from "#utils/common"; +import { randSeedInt, randSeedItem } from "#utils/common"; import { getRandomLocaleEntry } from "#utils/i18n"; import { getPokemonSpecies } from "#utils/pokemon-utils"; import { toCamelCase } from "#utils/strings"; @@ -61,9 +61,7 @@ export class Trainer extends Phaser.GameObjects.Container { this.variant = variant; this.partyTemplateIndex = Math.min( - partyTemplateIndex !== undefined - ? partyTemplateIndex - : randSeedWeightedItem(this.config.partyTemplates.map((_, i) => i)), + partyTemplateIndex !== undefined ? partyTemplateIndex : randSeedItem(this.config.partyTemplates.map((_, i) => i)), this.config.partyTemplates.length - 1, ); // TODO: Rework this and add actual error handling for missing names diff --git a/src/loading-scene.ts b/src/loading-scene.ts index 0a42fc3fa7d..e1b658f578a 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -138,19 +138,13 @@ export class LoadingScene extends SceneBase { this.loadImage("summary_profile", "ui"); this.loadImage("summary_profile_prompt_z", "ui"); // The pixel Z button prompt this.loadImage("summary_profile_prompt_a", "ui"); // The pixel A button prompt - this.loadImage("summary_profile_ability", "ui"); // Pixel text 'ABILITY' - this.loadImage("summary_profile_passive", "ui"); // Pixel text 'PASSIVE' this.loadImage("summary_status", "ui"); this.loadImage("summary_stats", "ui"); this.loadImage("summary_stats_overlay_exp", "ui"); this.loadImage("summary_moves", "ui"); this.loadImage("summary_moves_effect", "ui"); this.loadImage("summary_moves_overlay_row", "ui"); - this.loadImage("summary_moves_overlay_pp", "ui"); this.loadAtlas("summary_moves_cursor", "ui"); - for (let t = 1; t <= 3; t++) { - this.loadImage(`summary_tabs_${t}`, "ui"); - } this.loadImage("scroll_bar", "ui"); this.loadImage("scroll_bar_handle", "ui"); @@ -230,23 +224,91 @@ export class LoadingScene extends SceneBase { this.loadAtlas("pb", ""); this.loadAtlas("items", ""); - this.loadAtlas("types", ""); // Get current lang and load the types atlas for it. English will only load types while all other languages will load types and types_ - const lang = i18next.resolvedLanguage; - if (lang !== "en") { - if (hasAllLocalizedSprites(lang)) { - this.loadAtlas(`statuses_${lang}`, ""); - this.loadAtlas(`types_${lang}`, ""); - } else { - // Fallback to English - this.loadAtlas("statuses", ""); - this.loadAtlas("types", ""); - } - } else { - this.loadAtlas("statuses", ""); - this.loadAtlas("types", ""); + const lang = i18next.resolvedLanguage ?? "en"; + const keySuffix = lang !== "en" && hasAllLocalizedSprites(lang) ? `_${lang}` : ""; + + this.loadAtlas(`statuses${keySuffix}`, ""); + this.loadAtlas(`types${keySuffix}`, ""); + for (let t = 1; t <= 3; t++) { + this.loadImage( + `summary_tabs_${t}${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_tabs_${t}${keySuffix}.png`, + ); } + this.loadImage( + `summary_dexnb_label${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_dexnb_label${keySuffix}.png`, + ); // Pixel text 'No' + this.loadImage( + `summary_dexnb_label_overlay_shiny${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_dexnb_label_overlay_shiny${keySuffix}.png`, + ); // Pixel text 'No' shiny + this.loadImage( + `summary_profile_profile_title${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_profile_profile_title${keySuffix}.png`, + ); // Pixel text 'PROFILE' + this.loadImage( + `summary_profile_ability${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_profile_ability${keySuffix}.png`, + ); // Pixel text 'ABILITY' + this.loadImage( + `summary_profile_passive${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_profile_passive${keySuffix}.png`, + ); // Pixel text 'PASSIVE' + this.loadImage( + `summary_profile_memo_title${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_profile_memo_title${keySuffix}.png`, + ); // Pixel text 'TRAINER MEMO' + this.loadImage( + `summary_stats_item_title${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_stats_item_title${keySuffix}.png`, + ); // Pixel text 'ITEM' + this.loadImage( + `summary_stats_stats_title${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_stats_stats_title${keySuffix}.png`, + ); // Pixel text 'STATS' + this.loadImage( + `summary_stats_exp_title${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_stats_exp_title${keySuffix}.png`, + ); // Pixel text 'EXP.' + this.loadImage( + `summary_stats_expbar_title${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_stats_expbar_title${keySuffix}.png`, + ); // Pixel mini text 'EXP' + this.loadImage( + `summary_moves_moves_title${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_moves_moves_title${keySuffix}.png`, + ); // Pixel text 'MOVES' + this.loadImage( + `summary_moves_descriptions_title${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_moves_descriptions_title${keySuffix}.png`, + ); // Pixel text 'DESCRIPTIONS' + this.loadImage( + `summary_moves_overlay_pp${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_moves_overlay_pp${keySuffix}.png`, + ); // Pixel text 'PP' + this.loadImage( + `summary_moves_effect_title${keySuffix}`, + "ui", + `text_images/${lang}/summary/summary_moves_effect_title${keySuffix}.png`, + ); // Pixel text 'EFFECT' + if (timedEventManager.activeEventHasBanner()) { const availableLangs = timedEventManager.getEventBannerLangs(); if (lang && availableLangs.includes(lang)) { @@ -256,7 +318,6 @@ export class LoadingScene extends SceneBase { } } - this.loadAtlas("statuses", ""); this.loadAtlas("categories", ""); this.loadAtlas("egg", "egg"); diff --git a/src/main.ts b/src/main.ts index 7e4943bdca5..80f2ca3ed8b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,6 +10,10 @@ import InputTextPlugin from "phaser3-rex-plugins/plugins/inputtext-plugin"; import TransitionImagePackPlugin from "phaser3-rex-plugins/templates/transitionimagepack/transitionimagepack-plugin"; import UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin"; +if (import.meta.env.DEV) { + document.title += " (Beta)"; +} + // Catch global errors and display them in an alert so users can report the issue. window.onerror = (_message, _source, _lineno, _colno, error) => { console.error(error); diff --git a/src/phase-manager.ts b/src/phase-manager.ts index aa01a0ffc10..281ac8bd671 100644 --- a/src/phase-manager.ts +++ b/src/phase-manager.ts @@ -236,7 +236,7 @@ export class PhaseManager { /** Parallel array to {@linkcode dynamicPhaseQueues} - matches phase types to their queues */ private dynamicPhaseTypes: Constructor[]; - private currentPhase: Phase | null = null; + private currentPhase: Phase; private standbyPhase: Phase | null = null; constructor() { @@ -260,7 +260,9 @@ export class PhaseManager { } /* Phase Functions */ - getCurrentPhase(): Phase | null { + + /** @returns The currently running {@linkcode Phase}. */ + getCurrentPhase(): Phase { return this.currentPhase; } @@ -355,44 +357,43 @@ export class PhaseManager { if (this.phaseQueuePrependSpliceIndex > -1) { this.clearPhaseQueueSplice(); } - if (this.phaseQueuePrepend.length) { - while (this.phaseQueuePrepend.length) { - const poppedPhase = this.phaseQueuePrepend.pop(); - if (poppedPhase) { - this.phaseQueue.unshift(poppedPhase); - } + this.phaseQueue.unshift(...this.phaseQueuePrepend); + this.phaseQueuePrepend.splice(0); + + const unactivatedConditionalPhases: [() => boolean, Phase][] = []; + // Check if there are any conditional phases queued + for (const [condition, phase] of this.conditionalQueue) { + // Evaluate the condition associated with the phase + if (condition()) { + // If the condition is met, add the phase to the phase queue + this.pushPhase(phase); + } else { + // If the condition is not met, re-add the phase back to the end of the conditional queue + unactivatedConditionalPhases.push([condition, phase]); } } + + this.conditionalQueue = unactivatedConditionalPhases; + + // If no phases are left, unshift phases to start a new turn. if (!this.phaseQueue.length) { this.populatePhaseQueue(); // Clear the conditionalQueue if there are no phases left in the phaseQueue this.conditionalQueue = []; } - this.currentPhase = this.phaseQueue.shift() ?? null; + // Bang is justified as `populatePhaseQueue` ensures we always have _something_ in the queue at all times + this.currentPhase = this.phaseQueue.shift()!; - const unactivatedConditionalPhases: [() => boolean, Phase][] = []; - // Check if there are any conditional phases queued - while (this.conditionalQueue?.length) { - // Retrieve the first conditional phase from the queue - const conditionalPhase = this.conditionalQueue.shift(); - // Evaluate the condition associated with the phase - if (conditionalPhase?.[0]()) { - // If the condition is met, add the phase to the phase queue - this.pushPhase(conditionalPhase[1]); - } else if (conditionalPhase) { - // If the condition is not met, re-add the phase back to the front of the conditional queue - unactivatedConditionalPhases.push(conditionalPhase); - } else { - console.warn("condition phase is undefined/null!", conditionalPhase); - } - } - this.conditionalQueue.push(...unactivatedConditionalPhases); + this.startCurrentPhase(); + } - if (this.currentPhase) { - console.log(`%cStart Phase ${this.currentPhase.constructor.name}`, "color:green;"); - this.currentPhase.start(); - } + /** + * Helper method to start and log the current phase. + */ + private startCurrentPhase(): void { + console.log(`%cStart Phase ${this.currentPhase.phaseName}`, "color:green;"); + this.currentPhase.start(); } overridePhase(phase: Phase): boolean { @@ -402,8 +403,7 @@ export class PhaseManager { this.standbyPhase = this.currentPhase; this.currentPhase = phase; - console.log(`%cStart Phase ${phase.constructor.name}`, "color:green;"); - phase.start(); + this.startCurrentPhase(); return true; } @@ -520,6 +520,25 @@ export class PhaseManager { this.dynamicPhaseQueues[type].push(phase); } + /** + * Attempt to remove one or more Phases from the given DynamicPhaseQueue, removing the equivalent amount of {@linkcode ActivatePriorityQueuePhase}s from the queue. + * @param type - The {@linkcode DynamicPhaseType} to check + * @param phaseFilter - The function to select phases for removal + * @param removeCount - The maximum number of phases to remove, or `all` to remove all matching phases; + * default `1` + * @todo Remove this eventually once the patchwork bug this is used for is fixed + */ + public tryRemoveDynamicPhase( + type: DynamicPhaseType, + phaseFilter: (phase: Phase) => boolean, + removeCount: number | "all" = 1, + ): void { + const numRemoved = this.dynamicPhaseQueues[type].tryRemovePhase(phaseFilter, removeCount); + for (let x = 0; x < numRemoved; x++) { + this.tryRemovePhase(p => p.is("ActivatePriorityQueuePhase")); + } + } + /** * Unshifts the top phase from the corresponding dynamic queue onto {@linkcode phaseQueue} * @param type {@linkcode DynamicPhaseType} The type of dynamic phase to start diff --git a/src/phases/command-phase.ts b/src/phases/command-phase.ts index 6ca0679af4d..37e07c6c282 100644 --- a/src/phases/command-phase.ts +++ b/src/phases/command-phase.ts @@ -456,7 +456,7 @@ export class CommandPhase extends FieldPhase { const numBallTypes = 5; if (cursor < numBallTypes) { - const targetPokemon = globalScene.getEnemyPokemon(); + const targetPokemon = globalScene.getEnemyPokemon(false); if ( targetPokemon?.isBoss() && targetPokemon?.bossSegmentIndex >= 1 && diff --git a/src/phases/egg-hatch-phase.ts b/src/phases/egg-hatch-phase.ts index e9d28e0fe2a..547ca778c6b 100644 --- a/src/phases/egg-hatch-phase.ts +++ b/src/phases/egg-hatch-phase.ts @@ -64,7 +64,7 @@ export class EggHatchPhase extends Phase { private canSkip: boolean; private skipped: boolean; /** The sound effect being played when the egg is hatched */ - private evolutionBgm: AnySound; + private evolutionBgm: AnySound | null; private eggLapsePhase: EggLapsePhase; constructor(hatchScene: EggLapsePhase, egg: Egg, eggsToHatchCount: number) { diff --git a/src/phases/evolution-phase.ts b/src/phases/evolution-phase.ts index ad3db97d520..6095dfafa21 100644 --- a/src/phases/evolution-phase.ts +++ b/src/phases/evolution-phase.ts @@ -28,9 +28,10 @@ export class EvolutionPhase extends Phase { private evolution: SpeciesFormEvolution | null; private fusionSpeciesEvolved: boolean; // Whether the evolution is of the fused species - private evolutionBgm: AnySound; + private evolutionBgm: AnySound | null; private evolutionHandler: EvolutionSceneHandler; + /** Container for all assets used by the scene. When the scene is cleared, the children within this are destroyed. */ protected evolutionContainer: Phaser.GameObjects.Container; protected evolutionBaseBg: Phaser.GameObjects.Image; protected evolutionBg: Phaser.GameObjects.Video; @@ -297,7 +298,9 @@ export class EvolutionPhase extends Phase { this.evolutionBg.setVisible(false); }, }); - SoundFade.fadeOut(globalScene, this.evolutionBgm, 100); + if (this.evolutionBgm) { + SoundFade.fadeOut(globalScene, this.evolutionBgm, 100); + } } /** @@ -377,7 +380,9 @@ export class EvolutionPhase extends Phase { * Fadeout evolution music, play the cry, show the evolution completed text, and end the phase */ private onEvolutionComplete(evolvedPokemon: Pokemon) { - SoundFade.fadeOut(globalScene, this.evolutionBgm, 100); + if (this.evolutionBgm) { + SoundFade.fadeOut(globalScene, this.evolutionBgm, 100); + } globalScene.time.delayedCall(250, () => { this.pokemon.cry(); globalScene.time.delayedCall(1250, () => { @@ -522,6 +527,7 @@ export class EvolutionPhase extends Phase { return; } if (i === lastCycle) { + this.pokemonTintSprite.setVisible(false).setActive(false); this.pokemonEvoTintSprite.setScale(1); } }, diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 767d7a79968..c8dcbae907c 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -400,10 +400,17 @@ export class MoveEffectPhase extends PokemonPhase { * @param user - The {@linkcode Pokemon} using this phase's invoked move * @param target - {@linkcode Pokemon} the current target of this phase's invoked move * @param hitResult - The {@linkcode HitResult} of the attempted move + * @param damage - The amount of damage dealt to the target in the interaction * @param wasCritical - `true` if the move was a critical hit */ - protected applyOnGetHitAbEffects(user: Pokemon, target: Pokemon, hitResult: HitResult, wasCritical = false): void { - const params = { pokemon: target, opponent: user, move: this.move, hitResult }; + protected applyOnGetHitAbEffects( + user: Pokemon, + target: Pokemon, + hitResult: HitResult, + damage: number, + wasCritical = false, + ): void { + const params = { pokemon: target, opponent: user, move: this.move, hitResult, damage }; applyAbAttrs("PostDefendAbAttr", params); if (wasCritical) { @@ -763,12 +770,12 @@ export class MoveEffectPhase extends PokemonPhase { this.triggerMoveEffects(MoveEffectTrigger.PRE_APPLY, user, target); - const [hitResult, wasCritical] = this.applyMove(user, target, effectiveness); + const [hitResult, wasCritical, dmg] = this.applyMove(user, target, effectiveness); // Apply effects to the user (always) and the target (if not blocked by substitute). this.triggerMoveEffects(MoveEffectTrigger.POST_APPLY, user, target, firstTarget, true); if (!this.move.hitsSubstitute(user, target)) { - this.applyOnTargetEffects(user, target, hitResult, firstTarget, wasCritical); + this.applyOnTargetEffects(user, target, hitResult, firstTarget, dmg, wasCritical); } if (this.lastHit) { globalScene.triggerPokemonFormChange(user, SpeciesFormChangePostMoveTrigger); @@ -788,9 +795,13 @@ export class MoveEffectPhase extends PokemonPhase { * @param user - The {@linkcode Pokemon} using this phase's invoked move * @param target - The {@linkcode Pokemon} targeted by the move * @param effectiveness - The effectiveness of the move against the target - * @returns The {@linkcode HitResult} of the move against the target and a boolean indicating whether the target was crit + * @returns The {@linkcode HitResult} of the move against the target, a boolean indicating whether the target was crit, and the amount of damage dealt */ - protected applyMoveDamage(user: Pokemon, target: Pokemon, effectiveness: TypeDamageMultiplier): [HitResult, boolean] { + protected applyMoveDamage( + user: Pokemon, + target: Pokemon, + effectiveness: TypeDamageMultiplier, + ): [result: HitResult, critical: boolean, damage: number] { const isCritical = target.getCriticalHitResult(user, this.move); /* @@ -821,7 +832,7 @@ export class MoveEffectPhase extends PokemonPhase { const isOneHitKo = result === HitResult.ONE_HIT_KO; if (!dmg) { - return [result, false]; + return [result, false, 0]; } target.lapseTags(BattlerTagLapseType.HIT); @@ -850,7 +861,7 @@ export class MoveEffectPhase extends PokemonPhase { } if (damage <= 0) { - return [result, isCritical]; + return [result, isCritical, damage]; } if (user.isPlayer()) { @@ -879,7 +890,7 @@ export class MoveEffectPhase extends PokemonPhase { globalScene.applyModifiers(DamageMoneyRewardModifier, true, user, new NumberHolder(damage)); } - return [result, isCritical]; + return [result, isCritical, damage]; } /** @@ -932,12 +943,17 @@ export class MoveEffectPhase extends PokemonPhase { * @param user - The {@linkcode Pokemon} using this phase's invoked move * @param target - The {@linkcode Pokemon} struck by the move * @param effectiveness - The effectiveness of the move against the target + * @returns The {@linkcode HitResult} of the move against the target, a boolean indicating whether the target was crit, and the amount of damage dealt */ - protected applyMove(user: Pokemon, target: Pokemon, effectiveness: TypeDamageMultiplier): [HitResult, boolean] { + protected applyMove( + user: Pokemon, + target: Pokemon, + effectiveness: TypeDamageMultiplier, + ): [HitResult, critical: boolean, damage: number] { const moveCategory = user.getMoveCategory(target, this.move); if (moveCategory === MoveCategory.STATUS) { - return [HitResult.STATUS, false]; + return [HitResult.STATUS, false, 0]; } const result = this.applyMoveDamage(user, target, effectiveness); @@ -960,6 +976,7 @@ export class MoveEffectPhase extends PokemonPhase { * @param target - The {@linkcode Pokemon} targeted by the move * @param hitResult - The {@linkcode HitResult} obtained from applying the move * @param firstTarget - `true` if the target is the first Pokemon hit by the attack + * @param damage - The amount of damage dealt to the target in the interaction * @param wasCritical - `true` if the move was a critical hit */ protected applyOnTargetEffects( @@ -967,6 +984,7 @@ export class MoveEffectPhase extends PokemonPhase { target: Pokemon, hitResult: HitResult, firstTarget: boolean, + damage: number, wasCritical = false, ): void { /** Does {@linkcode hitResult} indicate that damage was dealt to the target? */ @@ -979,8 +997,8 @@ export class MoveEffectPhase extends PokemonPhase { this.triggerMoveEffects(MoveEffectTrigger.POST_APPLY, user, target, firstTarget, false); this.applyHeldItemFlinchCheck(user, target, dealsDamage); - this.applyOnGetHitAbEffects(user, target, hitResult, wasCritical); - applyAbAttrs("PostAttackAbAttr", { pokemon: user, opponent: target, move: this.move, hitResult }); + this.applyOnGetHitAbEffects(user, target, hitResult, damage, wasCritical); + applyAbAttrs("PostAttackAbAttr", { pokemon: user, opponent: target, move: this.move, hitResult, damage: damage }); // We assume only enemy Pokemon are able to have the EnemyAttackStatusEffectChanceModifier from tokens if (!user.isPlayer() && this.move.is("AttackMove")) { diff --git a/src/phases/party-heal-phase.ts b/src/phases/party-heal-phase.ts index 1030d5eb9d9..154e95bc970 100644 --- a/src/phases/party-heal-phase.ts +++ b/src/phases/party-heal-phase.ts @@ -38,13 +38,15 @@ export class PartyHealPhase extends BattlePhase { pokemon.updateInfo(true); } const healSong = globalScene.playSoundWithoutBgm("heal"); - globalScene.time.delayedCall(fixedInt(healSong.totalDuration * 1000), () => { - healSong.destroy(); - if (this.resumeBgm && bgmPlaying) { - globalScene.playBgm(); - } - globalScene.ui.fadeIn(500).then(() => this.end()); - }); + if (healSong) { + globalScene.time.delayedCall(fixedInt(healSong.totalDuration * 1000), () => { + healSong.destroy(); + if (this.resumeBgm && bgmPlaying) { + globalScene.playBgm(); + } + globalScene.ui.fadeIn(500).then(() => this.end()); + }); + } }); globalScene.arena.playerTerasUsed = 0; } diff --git a/src/phases/scan-ivs-phase.ts b/src/phases/scan-ivs-phase.ts index eebee28bfbb..38b39b310e1 100644 --- a/src/phases/scan-ivs-phase.ts +++ b/src/phases/scan-ivs-phase.ts @@ -24,7 +24,6 @@ export class ScanIvsPhase extends PokemonPhase { let statsContainer: Phaser.GameObjects.Sprite[] = []; let statsContainerLabels: Phaser.GameObjects.Sprite[] = []; const enemyField = globalScene.getEnemyField(); - const uiTheme = globalScene.uiTheme; // Assuming uiTheme is accessible for (let e = 0; e < enemyField.length; e++) { enemyIvs = enemyField[e].ivs; // we are using getRootSpeciesId() here because we want to check against the baby form, not the mid form if it exists @@ -36,8 +35,8 @@ export class ScanIvsPhase extends PokemonPhase { if (enemyIvs[ivStat] > currentIvs[ivStat] && PERMANENT_STATS.indexOf(Number(ivStat)) >= 0) { const hexColour = enemyIvs[ivStat] === 31 - ? getTextColor(TextStyle.PERFECT_IV, false, uiTheme) - : getTextColor(TextStyle.SUMMARY_GREEN, false, uiTheme); + ? getTextColor(TextStyle.PERFECT_IV, false) + : getTextColor(TextStyle.SUMMARY_GREEN, false); const hexTextColour = Phaser.Display.Color.HexStringToColor(hexColour).color; statsContainerLabels[s].setTint(hexTextColour); } diff --git a/src/phases/select-modifier-phase.ts b/src/phases/select-modifier-phase.ts index 05c890136ee..06a02af38b0 100644 --- a/src/phases/select-modifier-phase.ts +++ b/src/phases/select-modifier-phase.ts @@ -177,7 +177,7 @@ export class SelectModifierPhase extends BattlePhase { this.openModifierMenu(modifierType, cost, modifierSelectCallback); } } else { - this.applyModifier(modifierType.newModifier()!); + this.applyModifier(modifierType.newModifier()!, cost); } return cost === -1; } diff --git a/src/phases/switch-phase.ts b/src/phases/switch-phase.ts index a431d973a02..eaa8a723745 100644 --- a/src/phases/switch-phase.ts +++ b/src/phases/switch-phase.ts @@ -1,4 +1,5 @@ import { globalScene } from "#app/global-scene"; +import { DynamicPhaseType } from "#enums/dynamic-phase-type"; import { SwitchType } from "#enums/switch-type"; import { UiMode } from "#enums/ui-mode"; import { BattlePhase } from "#phases/battle-phase"; @@ -75,8 +76,11 @@ export class SwitchPhase extends BattlePhase { if (slotIndex >= globalScene.currentBattle.getBattlerCount() && slotIndex < 6) { // Remove any pre-existing PostSummonPhase under the same field index. // Pre-existing PostSummonPhases may occur when this phase is invoked during a prompt to switch at the start of a wave. - globalScene.phaseManager.tryRemovePhase( + // TODO: Separate the animations from `SwitchSummonPhase` and co. into another phase and use that on initial switch - this is a band-aid fix + globalScene.phaseManager.tryRemoveDynamicPhase( + DynamicPhaseType.POST_SUMMON, p => p.is("PostSummonPhase") && p.player && p.fieldIndex === this.fieldIndex, + "all", ); const switchType = option === PartyOption.PASS_BATON ? SwitchType.BATON_PASS : this.switchType; globalScene.phaseManager.unshiftNew("SwitchSummonPhase", switchType, fieldIndex, slotIndex, this.doReturn); diff --git a/src/phases/turn-start-phase.ts b/src/phases/turn-start-phase.ts index 8fc7a763c8f..59211a9eb03 100644 --- a/src/phases/turn-start-phase.ts +++ b/src/phases/turn-start-phase.ts @@ -179,12 +179,11 @@ export class TurnStartPhase extends FieldPhase { // https://www.smogon.com/forums/threads/sword-shield-battle-mechanics-research.3655528/page-64#post-9244179 phaseManager.pushNew("WeatherEffectPhase"); + phaseManager.pushNew("PositionalTagPhase"); phaseManager.pushNew("BerryPhase"); - /** Add a new phase to check who should be taking status damage */ phaseManager.pushNew("CheckStatusEffectPhase", moveOrder); - phaseManager.pushNew("PositionalTagPhase"); phaseManager.pushNew("TurnEndPhase"); /* diff --git a/src/system/arena-data.ts b/src/system/arena-data.ts index b2a04f96a55..18620e15223 100644 --- a/src/system/arena-data.ts +++ b/src/system/arena-data.ts @@ -5,14 +5,14 @@ import { Terrain } from "#data/terrain"; import { Weather } from "#data/weather"; import type { BiomeId } from "#enums/biome-id"; import { Arena } from "#field/arena"; -import type { ArenaTagTypeData } from "#types/arena-tags"; +import type { ArenaTagData } from "#types/arena-tags"; import type { NonFunctionProperties } from "#types/type-helpers"; export interface SerializedArenaData { biome: BiomeId; weather: NonFunctionProperties | null; terrain: NonFunctionProperties | null; - tags?: ArenaTagTypeData[]; + tags?: ArenaTagData[]; positionalTags: SerializedPositionalTag[]; playerTerasUsed?: number; } @@ -31,7 +31,7 @@ export class ArenaData { // is not yet an instance of `ArenaTag` this.tags = source.tags - ?.map((t: ArenaTag | ArenaTagTypeData) => loadArenaTag(t)) + ?.map((t: ArenaTag | ArenaTagData) => loadArenaTag(t)) ?.filter((tag): tag is SerializableArenaTag => tag instanceof SerializableArenaTag) ?? []; this.playerTerasUsed = source.playerTerasUsed ?? 0; diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 3a4dafb2de2..47d3c2df2f5 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -1515,6 +1515,7 @@ export class GameData { switch (dataType) { case GameDataType.SYSTEM: { dataStr = this.convertSystemDataStr(dataStr); + dataStr = dataStr.replace(/"playTime":\d+/, `"playTime":${this.gameStats.playTime + 60}`); const systemData = this.parseSystemData(dataStr); valid = !!systemData.dexData && !!systemData.timestamp; break; diff --git a/src/ui-inputs.ts b/src/ui-inputs.ts index 71c5ac1049e..72ae59faaec 100644 --- a/src/ui-inputs.ts +++ b/src/ui-inputs.ts @@ -13,7 +13,7 @@ import { SettingsGamepadUiHandler } from "#ui/settings-gamepad-ui-handler"; import { SettingsKeyboardUiHandler } from "#ui/settings-keyboard-ui-handler"; import { SettingsUiHandler } from "#ui/settings-ui-handler"; import { StarterSelectUiHandler } from "#ui/starter-select-ui-handler"; -import type Phaser from "phaser"; +import Phaser from "phaser"; type ActionKeys = Record void>; @@ -224,25 +224,26 @@ export class UiInputs { buttonSpeedChange(up = true): void { const settingGameSpeed = settingIndex(SettingKeys.Game_Speed); + const settingOptions = Setting[settingGameSpeed].options; + let currentSetting = settingOptions.findIndex(item => item.value === globalScene.gameSpeed.toString()); + // if current setting is -1, then the current game speed is not a valid option, so default to index 5 (3x) + if (currentSetting === -1) { + currentSetting = 5; + } + let direction: number; if (up && globalScene.gameSpeed < 5) { - globalScene.gameData.saveSetting( - SettingKeys.Game_Speed, - Setting[settingGameSpeed].options.findIndex(item => item.label === `${globalScene.gameSpeed}x`) + 1, - ); - if (globalScene.ui?.getMode() === UiMode.SETTINGS) { - (globalScene.ui.getHandler() as SettingsUiHandler).show([]); - } + direction = 1; } else if (!up && globalScene.gameSpeed > 1) { - globalScene.gameData.saveSetting( - SettingKeys.Game_Speed, - Math.max( - Setting[settingGameSpeed].options.findIndex(item => item.label === `${globalScene.gameSpeed}x`) - 1, - 0, - ), - ); - if (globalScene.ui?.getMode() === UiMode.SETTINGS) { - (globalScene.ui.getHandler() as SettingsUiHandler).show([]); - } + direction = -1; + } else { + return; + } + globalScene.gameData.saveSetting( + SettingKeys.Game_Speed, + Phaser.Math.Clamp(currentSetting + direction, 0, settingOptions.length - 1), + ); + if (globalScene.ui?.getMode() === UiMode.SETTINGS) { + (globalScene.ui.getHandler() as SettingsUiHandler).show([]); } } } diff --git a/src/ui/abstract-option-select-ui-handler.ts b/src/ui/abstract-option-select-ui-handler.ts index b7279bc2d30..914dfca6ef3 100644 --- a/src/ui/abstract-option-select-ui-handler.ts +++ b/src/ui/abstract-option-select-ui-handler.ts @@ -81,7 +81,7 @@ export abstract class AbstractOptionSelectUiHandler extends UiHandler { this.optionSelectIcons = []; - this.scale = getTextStyleOptions(TextStyle.WINDOW, globalScene.uiTheme).scale; + this.scale = getTextStyleOptions(TextStyle.WINDOW).scale; this.setCursor(0); } @@ -124,8 +124,8 @@ export abstract class AbstractOptionSelectUiHandler extends UiHandler { optionsForWidth .map(o => o.item - ? `[shadow=${getTextColor(o.style ?? this.defaultTextStyle, true, globalScene.uiTheme)}][color=${getTextColor(o.style ?? TextStyle.WINDOW, false, globalScene.uiTheme)}] ${o.label}[/color][/shadow]` - : `[shadow=${getTextColor(o.style ?? this.defaultTextStyle, true, globalScene.uiTheme)}][color=${getTextColor(o.style ?? TextStyle.WINDOW, false, globalScene.uiTheme)}]${o.label}[/color][/shadow]`, + ? `[shadow=${getTextColor(o.style ?? this.defaultTextStyle, true)}][color=${getTextColor(o.style ?? TextStyle.WINDOW, false)}] ${o.label}[/color][/shadow]` + : `[shadow=${getTextColor(o.style ?? this.defaultTextStyle, true)}][color=${getTextColor(o.style ?? TextStyle.WINDOW, false)}]${o.label}[/color][/shadow]`, ) .join("\n"), TextStyle.WINDOW, @@ -149,8 +149,8 @@ export abstract class AbstractOptionSelectUiHandler extends UiHandler { this.textContent = optionsWithScroll .map(o => o.item - ? `[shadow=${getTextColor(o.style ?? this.defaultTextStyle, true, globalScene.uiTheme)}][color=${getTextColor(o.style ?? TextStyle.WINDOW, false, globalScene.uiTheme)}] ${o.label}[/color][/shadow]` - : `[shadow=${getTextColor(o.style ?? this.defaultTextStyle, true, globalScene.uiTheme)}][color=${getTextColor(o.style ?? TextStyle.WINDOW, false, globalScene.uiTheme)}]${o.label}[/color][/shadow]`, + ? `[shadow=${getTextColor(o.style ?? this.defaultTextStyle, true)}][color=${getTextColor(o.style ?? TextStyle.WINDOW, false)}] ${o.label}[/color][/shadow]` + : `[shadow=${getTextColor(o.style ?? this.defaultTextStyle, true)}][color=${getTextColor(o.style ?? TextStyle.WINDOW, false)}]${o.label}[/color][/shadow]`, ) .join("\n"); this.optionSelectText.setText(this.textContent); diff --git a/src/ui/admin-ui-handler.ts b/src/ui/admin-ui-handler.ts index e577368363d..3af34f14e2d 100644 --- a/src/ui/admin-ui-handler.ts +++ b/src/ui/admin-ui-handler.ts @@ -7,6 +7,7 @@ import type { InputFieldConfig } from "#ui/form-modal-ui-handler"; import { FormModalUiHandler } from "#ui/form-modal-ui-handler"; import type { ModalConfig } from "#ui/modal-ui-handler"; import { toTitleCase } from "#utils/strings"; +import { getTextColor } from "./text"; type AdminUiHandlerService = "discord" | "google"; type AdminUiHandlerServiceMode = "Link" | "Unlink"; @@ -129,11 +130,11 @@ export class AdminUiHandler extends FormModalUiHandler { this.errorMessage.setPosition(10, (hasTitle ? 31 : 5) + 20 * (fields.length - 1) + 16 + this.getButtonTopMargin()); // sets the position of the message dynamically if (isMessageError) { - this.errorMessage.setColor(this.getTextColor(TextStyle.SUMMARY_PINK)); - this.errorMessage.setShadowColor(this.getTextColor(TextStyle.SUMMARY_PINK, true)); + this.errorMessage.setColor(getTextColor(TextStyle.SUMMARY_PINK)); + this.errorMessage.setShadowColor(getTextColor(TextStyle.SUMMARY_PINK, true)); } else { - this.errorMessage.setColor(this.getTextColor(TextStyle.SUMMARY_GREEN)); - this.errorMessage.setShadowColor(this.getTextColor(TextStyle.SUMMARY_GREEN, true)); + this.errorMessage.setColor(getTextColor(TextStyle.SUMMARY_GREEN)); + this.errorMessage.setShadowColor(getTextColor(TextStyle.SUMMARY_GREEN, true)); } if (super.show(args)) { diff --git a/src/ui/ball-ui-handler.ts b/src/ui/ball-ui-handler.ts index 99dabd893df..3d8efca96b8 100644 --- a/src/ui/ball-ui-handler.ts +++ b/src/ui/ball-ui-handler.ts @@ -26,7 +26,7 @@ export class BallUiHandler extends UiHandler { setup() { const ui = this.getUi(); - this.scale = getTextStyleOptions(TextStyle.WINDOW, globalScene.uiTheme).scale; + this.scale = getTextStyleOptions(TextStyle.WINDOW).scale; let optionsTextContent = ""; diff --git a/src/ui/battle-info/battle-info.ts b/src/ui/battle-info/battle-info.ts index 810d0c7c328..4d2cf597ed2 100644 --- a/src/ui/battle-info/battle-info.ts +++ b/src/ui/battle-info/battle-info.ts @@ -5,6 +5,7 @@ import { PokemonType } from "#enums/pokemon-type"; import { Stat } from "#enums/stat"; import { StatusEffect } from "#enums/status-effect"; import { TextStyle } from "#enums/text-style"; +import { UiTheme } from "#enums/ui-theme"; import type { Pokemon } from "#field/pokemon"; import { getVariantTint } from "#sprites/variant"; import { addTextObject } from "#ui/text"; @@ -265,7 +266,7 @@ export abstract class BattleInfo extends Phaser.GameObjects.Container { this.add(this.hpBar); this.levelNumbersContainer = globalScene.add - .container(9.5, globalScene.uiTheme ? 0 : -0.5) + .container(9.5, globalScene.uiTheme === UiTheme.LEGACY ? 0 : -0.5) .setName("container_level"); this.levelContainer.add(this.levelNumbersContainer); @@ -287,9 +288,6 @@ export abstract class BattleInfo extends Phaser.GameObjects.Container { 2.5, ); this.splicedIcon.setVisible(pokemon.isFusion(true)); - if (!this.splicedIcon.visible) { - return; - } this.splicedIcon .on("pointerover", () => globalScene.ui.showTooltip( @@ -323,6 +321,10 @@ export abstract class BattleInfo extends Phaser.GameObjects.Container { .setVisible(pokemon.isShiny()) .setTint(getVariantTint(baseVariant)); + this.shinyIcon + .on("pointerover", () => globalScene.ui.showTooltip("", i18next.t("common:shinyOnHover") + shinyDescriptor)) + .on("pointerout", () => globalScene.ui.hideTooltip()); + if (!this.shinyIcon.visible) { return; } @@ -335,10 +337,6 @@ export abstract class BattleInfo extends Phaser.GameObjects.Container { } shinyDescriptor += ")"; } - - this.shinyIcon - .on("pointerover", () => globalScene.ui.showTooltip("", i18next.t("common:shinyOnHover") + shinyDescriptor)) - .on("pointerout", () => globalScene.ui.hideTooltip()); } initInfo(pokemon: Pokemon) { diff --git a/src/ui/battle-info/enemy-battle-info.ts b/src/ui/battle-info/enemy-battle-info.ts index d426a49df5c..0feb314a2e7 100644 --- a/src/ui/battle-info/enemy-battle-info.ts +++ b/src/ui/battle-info/enemy-battle-info.ts @@ -1,6 +1,7 @@ import { globalScene } from "#app/global-scene"; import { Stat } from "#enums/stat"; import { TextStyle } from "#enums/text-style"; +import { UiTheme } from "#enums/ui-theme"; import type { EnemyPokemon } from "#field/pokemon"; import { BattleFlyout } from "#ui/battle-flyout"; import type { BattleInfoParamList } from "#ui/battle-info"; @@ -36,7 +37,7 @@ export class EnemyBattleInfo extends BattleInfo { override constructTypeIcons(): void { this.type1Icon = globalScene.add.sprite(-15, -15.5, "pbinfo_enemy_type1").setName("icon_type_1").setOrigin(0); this.type2Icon = globalScene.add.sprite(-15, -2.5, "pbinfo_enemy_type2").setName("icon_type_2").setOrigin(0); - this.type3Icon = globalScene.add.sprite(0, 15.5, "pbinfo_enemy_type3").setName("icon_type_3").setOrigin(0); + this.type3Icon = globalScene.add.sprite(0, -15.5, "pbinfo_enemy_type").setName("icon_type_3").setOrigin(0); this.add([this.type1Icon, this.type2Icon, this.type3Icon]); } @@ -115,6 +116,9 @@ export class EnemyBattleInfo extends BattleInfo { globalScene.gameData.starterData[pokemon.species.getRootSpeciesId()].classicWinCount > 0 && globalScene.gameData.starterData[pokemon.species.getRootSpeciesId(true)].classicWinCount > 0 ) { + // move the ribbon to the left if there is no owned icon + const championRibbonX = this.ownedIcon.visible ? 8 : 0; + this.championRibbon.setPositionRelative(this.nameText, championRibbonX, 11.75); this.championRibbon.setVisible(true); } @@ -180,12 +184,12 @@ export class EnemyBattleInfo extends BattleInfo { this.ownedIcon, this.championRibbon, this.statusIndicator, - this.levelContainer, this.statValuesContainer, ].map(e => (e.x += 48 * (boss ? -1 : 1))); this.hpBar.x += 38 * (boss ? -1 : 1); this.hpBar.y += 2 * (this.boss ? -1 : 1); this.hpBar.setTexture(`overlay_hp${boss ? "_boss" : ""}`); + this.levelContainer.x += 2 * (boss ? -1 : 1); this.box.setTexture(this.getTextureName()); this.statsBox.setTexture(`${this.getTextureName()}_stats`); } @@ -200,7 +204,7 @@ export class EnemyBattleInfo extends BattleInfo { } if (this.boss && this.bossSegments > 1) { - const uiTheme = globalScene.uiTheme; + const isLegacyUiTheme = globalScene.uiTheme === UiTheme.LEGACY; const maxHp = pokemon.getMaxHp(); for (let s = 1; s < this.bossSegments; s++) { const dividerX = (Math.round((maxHp / this.bossSegments) * s) / maxHp) * this.hpBar.width; @@ -208,14 +212,14 @@ export class EnemyBattleInfo extends BattleInfo { 0, 0, 1, - this.hpBar.height - (uiTheme ? 0 : 1), + this.hpBar.height - (isLegacyUiTheme ? 0 : 1), pokemon.bossSegmentIndex >= s ? 0xffffff : 0x404040, ); divider.setOrigin(0.5, 0).setName("hpBar_divider_" + s.toString()); this.add(divider); this.moveBelow(divider as Phaser.GameObjects.GameObject, this.statsContainer); - divider.setPositionRelative(this.hpBar, dividerX, uiTheme ? 0 : 1); + divider.setPositionRelative(this.hpBar, dividerX, isLegacyUiTheme ? 0 : 1); this.hpBarSegmentDividers.push(divider); } } diff --git a/src/ui/battle-info/player-battle-info.ts b/src/ui/battle-info/player-battle-info.ts index 998f7cbb41f..f0b50748154 100644 --- a/src/ui/battle-info/player-battle-info.ts +++ b/src/ui/battle-info/player-battle-info.ts @@ -21,7 +21,7 @@ export class PlayerBattleInfo extends BattleInfo { override constructTypeIcons(): void { this.type1Icon = globalScene.add.sprite(-139, -17, "pbinfo_player_type1").setName("icon_type_1").setOrigin(0); this.type2Icon = globalScene.add.sprite(-139, -1, "pbinfo_player_type2").setName("icon_type_2").setOrigin(0); - this.type3Icon = globalScene.add.sprite(-154, -17, "pbinfo_player_type3").setName("icon_type_3").setOrigin(0); + this.type3Icon = globalScene.add.sprite(-154, -17, "pbinfo_player_type").setName("icon_type_3").setOrigin(0); this.add([this.type1Icon, this.type2Icon, this.type3Icon]); } diff --git a/src/ui/battle-message-ui-handler.ts b/src/ui/battle-message-ui-handler.ts index 2ecca06172b..bf4360b37bf 100644 --- a/src/ui/battle-message-ui-handler.ts +++ b/src/ui/battle-message-ui-handler.ts @@ -245,7 +245,6 @@ export class BattleMessageUiHandler extends MessageUiHandler { getIvDescriptor(value: number, typeIv: number, pokemonId: number): string { const starterSpecies = globalScene.getPokemonById(pokemonId)!.species.getRootSpeciesId(); // we are using getRootSpeciesId() here because we want to check against the baby form, not the mid form if it exists const starterIvs: number[] = globalScene.gameData.dexData[starterSpecies].ivs; - const uiTheme = globalScene.uiTheme; // Assuming uiTheme is accessible // Function to wrap text in color based on comparison const coloredText = (text: string, isBetter: boolean, ivValue) => { @@ -259,8 +258,8 @@ export class BattleMessageUiHandler extends MessageUiHandler { } else { textStyle = TextStyle.WINDOW; } - const color = getTextColor(textStyle, false, uiTheme); - return `[color=${color}][shadow=${getTextColor(textStyle, true, uiTheme)}]${text}[/shadow][/color]`; + const color = getTextColor(textStyle, false); + return `[color=${color}][shadow=${getTextColor(textStyle, true)}]${text}[/shadow][/color]`; }; if (value > 30) { diff --git a/src/ui/challenges-select-ui-handler.ts b/src/ui/challenges-select-ui-handler.ts index b37ddcc6a5f..68559b92439 100644 --- a/src/ui/challenges-select-ui-handler.ts +++ b/src/ui/challenges-select-ui-handler.ts @@ -383,14 +383,14 @@ export class GameChallengesUiHandler extends UiHandler { this.updateChallengeArrows(this.startCursor.visible); } else { globalScene.phaseManager.toTitleScreen(); - globalScene.phaseManager.getCurrentPhase()?.end(); + globalScene.phaseManager.getCurrentPhase().end(); } success = true; } else if (button === Button.SUBMIT || button === Button.ACTION) { if (this.hasSelectedChallenge) { if (this.startCursor.visible) { globalScene.phaseManager.unshiftNew("SelectStarterPhase"); - globalScene.phaseManager.getCurrentPhase()?.end(); + globalScene.phaseManager.getCurrentPhase().end(); } else { this.startCursor.setVisible(true); this.cursorObj?.setVisible(false); diff --git a/src/ui/egg-gacha-ui-handler.ts b/src/ui/egg-gacha-ui-handler.ts index e54ee445aee..d94ddcd6ee5 100644 --- a/src/ui/egg-gacha-ui-handler.ts +++ b/src/ui/egg-gacha-ui-handler.ts @@ -170,7 +170,7 @@ export class EggGachaUiHandler extends MessageUiHandler { setup() { this.gachaCursor = 0; - this.scale = getTextStyleOptions(TextStyle.WINDOW, globalScene.uiTheme).scale; + this.scale = getTextStyleOptions(TextStyle.WINDOW).scale; const ui = this.getUi(); diff --git a/src/ui/egg-hatch-scene-handler.ts b/src/ui/egg-hatch-scene-handler.ts index 6536ef2af80..1733b64144b 100644 --- a/src/ui/egg-hatch-scene-handler.ts +++ b/src/ui/egg-hatch-scene-handler.ts @@ -45,7 +45,7 @@ export class EggHatchSceneHandler extends UiHandler { processInput(button: Button): boolean { if (button === Button.ACTION || button === Button.CANCEL) { const phase = globalScene.phaseManager.getCurrentPhase(); - if (phase?.is("EggHatchPhase") && phase.trySkip()) { + if (phase.is("EggHatchPhase") && phase.trySkip()) { return true; } } diff --git a/src/ui/egg-summary-ui-handler.ts b/src/ui/egg-summary-ui-handler.ts index c66075dd910..db357b849c3 100644 --- a/src/ui/egg-summary-ui-handler.ts +++ b/src/ui/egg-summary-ui-handler.ts @@ -222,7 +222,7 @@ export class EggSummaryUiHandler extends MessageUiHandler { if (button === Button.CANCEL) { if (!this.blockExit) { const phase = globalScene.phaseManager.getCurrentPhase(); - if (phase?.is("EggSummaryPhase")) { + if (phase.is("EggSummaryPhase")) { phase.end(); } success = true; diff --git a/src/ui/fight-ui-handler.ts b/src/ui/fight-ui-handler.ts index 1d856079939..d1b85a29b14 100644 --- a/src/ui/fight-ui-handler.ts +++ b/src/ui/fight-ui-handler.ts @@ -13,7 +13,7 @@ import type { EnemyPokemon, Pokemon } from "#field/pokemon"; import type { PokemonMove } from "#moves/pokemon-move"; import type { CommandPhase } from "#phases/command-phase"; import { MoveInfoOverlay } from "#ui/move-info-overlay"; -import { addTextObject } from "#ui/text"; +import { addTextObject, getTextColor } from "#ui/text"; import { UiHandler } from "#ui/ui-handler"; import { fixedInt, getLocalizedSpriteKey, padInt } from "#utils/common"; import i18next from "i18next"; @@ -284,7 +284,7 @@ export class FightUiHandler extends UiHandler implements InfoToggle { const ppColorStyle = FightUiHandler.ppRatioToColor(pp / maxPP); // Changes the text color and shadow according to the determined TextStyle - this.ppText.setColor(this.getTextColor(ppColorStyle, false)).setShadowColor(this.getTextColor(ppColorStyle, true)); + this.ppText.setColor(getTextColor(ppColorStyle, false)).setShadowColor(getTextColor(ppColorStyle, true)); this.moveInfoOverlay.show(pokemonMove.getMove()); pokemon.getOpponents().forEach(opponent => { diff --git a/src/ui/filter-bar.ts b/src/ui/filter-bar.ts index ea227655a97..f33c2902295 100644 --- a/src/ui/filter-bar.ts +++ b/src/ui/filter-bar.ts @@ -97,9 +97,9 @@ export class FilterBar extends Phaser.GameObjects.Container { updateFilterLabels(): void { for (let i = 0; i < this.numFilters; i++) { if (this.dropDowns[i].hasDefaultValues()) { - this.labels[i].setColor(getTextColor(TextStyle.TOOLTIP_CONTENT, false, globalScene.uiTheme)); + this.labels[i].setColor(getTextColor(TextStyle.TOOLTIP_CONTENT, false)); } else { - this.labels[i].setColor(getTextColor(TextStyle.STATS_LABEL, false, globalScene.uiTheme)); + this.labels[i].setColor(getTextColor(TextStyle.STATS_LABEL, false)); } } } diff --git a/src/ui/filter-text.ts b/src/ui/filter-text.ts index d5809292c25..c9849469d5d 100644 --- a/src/ui/filter-text.ts +++ b/src/ui/filter-text.ts @@ -167,9 +167,9 @@ export class FilterText extends Phaser.GameObjects.Container { updateFilterLabels(): void { for (let i = 0; i < this.numFilters; i++) { if (this.selections[i].text === this.defaultText) { - this.labels[i].setColor(getTextColor(TextStyle.TOOLTIP_CONTENT, false, globalScene.uiTheme)); + this.labels[i].setColor(getTextColor(TextStyle.TOOLTIP_CONTENT, false)); } else { - this.labels[i].setColor(getTextColor(TextStyle.STATS_LABEL, false, globalScene.uiTheme)); + this.labels[i].setColor(getTextColor(TextStyle.STATS_LABEL, false)); } } } diff --git a/src/ui/form-modal-ui-handler.ts b/src/ui/form-modal-ui-handler.ts index 5c547465de9..092a0c85bb2 100644 --- a/src/ui/form-modal-ui-handler.ts +++ b/src/ui/form-modal-ui-handler.ts @@ -4,7 +4,7 @@ import { TextStyle } from "#enums/text-style"; import type { UiMode } from "#enums/ui-mode"; import type { ModalConfig } from "#ui/modal-ui-handler"; import { ModalUiHandler } from "#ui/modal-ui-handler"; -import { addTextInputObject, addTextObject } from "#ui/text"; +import { addTextInputObject, addTextObject, getTextColor } from "#ui/text"; import { addWindow, WindowVariant } from "#ui/ui-theme"; import { fixedInt } from "#utils/common"; import type InputText from "phaser3-rex-plugins/plugins/inputtext"; @@ -78,8 +78,8 @@ export abstract class FormModalUiHandler extends ModalUiHandler { wordWrap: { width: 850 }, }, ); - this.errorMessage.setColor(this.getTextColor(TextStyle.SUMMARY_PINK)); - this.errorMessage.setShadowColor(this.getTextColor(TextStyle.SUMMARY_PINK, true)); + this.errorMessage.setColor(getTextColor(TextStyle.SUMMARY_PINK)); + this.errorMessage.setShadowColor(getTextColor(TextStyle.SUMMARY_PINK, true)); this.errorMessage.setVisible(false); this.modalContainer.add(this.errorMessage); } diff --git a/src/ui/menu-ui-handler.ts b/src/ui/menu-ui-handler.ts index 4f6d6ede488..66465f76445 100644 --- a/src/ui/menu-ui-handler.ts +++ b/src/ui/menu-ui-handler.ts @@ -126,7 +126,7 @@ export class MenuUiHandler extends MessageUiHandler { const ui = this.getUi(); this.excludedMenus = () => [ { - condition: !!globalScene.phaseManager.getCurrentPhase()?.is("SelectModifierPhase"), + condition: globalScene.phaseManager.getCurrentPhase().is("SelectModifierPhase"), options: [MenuOptions.EGG_GACHA], }, { condition: bypassLogin, options: [MenuOptions.LOG_OUT] }, @@ -145,7 +145,7 @@ export class MenuUiHandler extends MessageUiHandler { ); this.optionSelectText.setLineSpacing(12); - this.scale = getTextStyleOptions(TextStyle.WINDOW, globalScene.uiTheme).scale; + this.scale = getTextStyleOptions(TextStyle.WINDOW).scale; this.menuBg = addWindow( globalScene.scaledCanvas.width - (this.optionSelectText.displayWidth + 25), 0, diff --git a/src/ui/modifier-select-ui-handler.ts b/src/ui/modifier-select-ui-handler.ts index a070b522050..9ddc892add6 100644 --- a/src/ui/modifier-select-ui-handler.ts +++ b/src/ui/modifier-select-ui-handler.ts @@ -65,7 +65,7 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler { const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); - const styleOptions = getTextStyleOptions(TextStyle.PARTY, globalScene.uiTheme).styleOptions; + const styleOptions = getTextStyleOptions(TextStyle.PARTY).styleOptions; if (context) { context.font = styleOptions.fontSize + "px " + styleOptions.fontFamily; @@ -686,14 +686,14 @@ export class ModifierSelectUiHandler extends AwaitableUiHandler { const formattedMoney = formatMoney(globalScene.moneyFormat, this.rerollCost); this.rerollCostText.setText(i18next.t("modifierSelectUiHandler:rerollCost", { formattedMoney })); - this.rerollCostText.setColor(this.getTextColor(canReroll ? TextStyle.MONEY : TextStyle.PARTY_RED)); - this.rerollCostText.setShadowColor(this.getTextColor(canReroll ? TextStyle.MONEY : TextStyle.PARTY_RED, true)); + this.rerollCostText.setColor(getTextColor(canReroll ? TextStyle.MONEY : TextStyle.PARTY_RED)); + this.rerollCostText.setShadowColor(getTextColor(canReroll ? TextStyle.MONEY : TextStyle.PARTY_RED, true)); } updateLockRaritiesText(): void { const textStyle = globalScene.lockModifierTiers ? TextStyle.SUMMARY_BLUE : TextStyle.PARTY; - this.lockRarityButtonText.setColor(this.getTextColor(textStyle)); - this.lockRarityButtonText.setShadowColor(this.getTextColor(textStyle, true)); + this.lockRarityButtonText.setColor(getTextColor(textStyle)); + this.lockRarityButtonText.setShadowColor(getTextColor(textStyle, true)); } clear() { @@ -1042,7 +1042,7 @@ class ModifierOption extends Phaser.GameObjects.Container { const formattedMoney = formatMoney(globalScene.moneyFormat, cost); this.itemCostText.setText(i18next.t("modifierSelectUiHandler:itemCost", { formattedMoney })); - this.itemCostText.setColor(getTextColor(textStyle, false, globalScene.uiTheme)); - this.itemCostText.setShadowColor(getTextColor(textStyle, true, globalScene.uiTheme)); + this.itemCostText.setColor(getTextColor(textStyle, false)); + this.itemCostText.setShadowColor(getTextColor(textStyle, true)); } } diff --git a/src/ui/party-ui-handler.ts b/src/ui/party-ui-handler.ts index d3c67f66ec9..b77710d8140 100644 --- a/src/ui/party-ui-handler.ts +++ b/src/ui/party-ui-handler.ts @@ -562,8 +562,11 @@ export class PartyUiHandler extends MessageUiHandler { private processModifierTransferModeInput(pokemon: PlayerPokemon) { const ui = this.getUi(); const option = this.options[this.optionsCursor]; + const allItems = this.getTransferrableItemsFromPokemon(pokemon); + // get the index of the "All" option. + const allCursorIndex = allItems.length; - if (option === PartyOption.TRANSFER) { + if (this.transferMode && option === PartyOption.TRANSFER) { return this.processTransferOption(); } @@ -573,31 +576,56 @@ export class PartyUiHandler extends MessageUiHandler { let ableToTransferText: string; for (let p = 0; p < globalScene.getPlayerParty().length; p++) { - // this for look goes through each of the party pokemon + // this for loop goes through each of the party pokemon const newPokemon = globalScene.getPlayerParty()[p]; // this next bit checks to see if the the selected item from the original transfer pokemon exists on the new pokemon `p` // this returns `undefined` if the new pokemon doesn't have the item at all, otherwise it returns the `pokemonHeldItemModifier` for that item - const matchingModifier = globalScene.findModifier( - m => - m.is("PokemonHeldItemModifier") && - m.pokemonId === newPokemon.id && - m.matchType(this.getTransferrableItemsFromPokemon(pokemon)[this.transferOptionCursor]), - ) as PokemonHeldItemModifier; + const matchingModifiers: (PokemonHeldItemModifier | undefined)[] = []; + if (this.transferOptionCursor === allCursorIndex) { + // if "All" is selected, check all items + for (const item of allItems) { + matchingModifiers.push( + globalScene.findModifier( + m => m.is("PokemonHeldItemModifier") && m.pokemonId === newPokemon.id && m.matchType(item), + ) as PokemonHeldItemModifier | undefined, + ); + } + } else { + // otherwise only check the selected item + matchingModifiers.push( + globalScene.findModifier( + m => + m.is("PokemonHeldItemModifier") && + m.pokemonId === newPokemon.id && + m.matchType(allItems[this.transferOptionCursor]), + ) as PokemonHeldItemModifier | undefined, + ); + } + const hasMatchingModifier = matchingModifiers.some(m => m !== undefined); // checks if any items match const partySlot = this.partySlots.filter(m => m.getPokemon() === newPokemon)[0]; // this gets pokemon [p] for us if (p !== this.transferCursor) { // this skips adding the able/not able labels on the pokemon doing the transfer - if (matchingModifier) { + if (hasMatchingModifier) { // if matchingModifier exists then the item exists on the new pokemon - if (matchingModifier.getMaxStackCount() === matchingModifier.stackCount) { - // checks to see if the stack of items is at max stack; if so, set the description label to "Not able" - ableToTransferText = i18next.t("partyUiHandler:notAble"); - } else { - // if the pokemon isn't at max stack, make the label "Able" - ableToTransferText = i18next.t("partyUiHandler:able"); + ableToTransferText = i18next.t("partyUiHandler:notAble"); // start with not able + /** + * The amount of items that can be transferred in the `All` option + */ + let ableAmount = 0; + for (const modifier of matchingModifiers) { + if (!modifier || modifier.getCountUnderMax() > 0) { + // if the modifier doesn't exist, or the stack count isn't at max, then we can transfer at least 1 stack + ableToTransferText = i18next.t("partyUiHandler:able"); + ableAmount++; + } } + // only show the amount if an item can be transferred and there are multiple items + ableToTransferText += ableAmount && matchingModifiers.length > 1 ? ` (${ableAmount})` : ""; } else { - // if matchingModifier doesn't exist, that means the pokemon doesn't have any of the item, and we need to show "Able" + // if no item matches, that means the pokemon doesn't have any of the item, and we need to show "Able" ableToTransferText = i18next.t("partyUiHandler:able"); + // only show the amount if there are multiple items + ableToTransferText += matchingModifiers.length > 1 ? ` (${matchingModifiers.length})` : ""; } } else { // this else relates to the transfer pokemon. We set the text to be blank so there's no "Able"/"Not able" text @@ -613,6 +641,20 @@ export class PartyUiHandler extends MessageUiHandler { ui.playSelect(); return true; } + + if (option === PartyOption.SUMMARY) { + return this.processSummaryOption(pokemon); + } + if (option === PartyOption.POKEDEX) { + return this.processPokedexOption(pokemon); + } + if (option === PartyOption.UNPAUSE_EVOLUTION) { + return this.processUnpauseEvolutionOption(pokemon); + } + if (option === PartyOption.RENAME) { + return this.processRenameOption(pokemon); + } + return false; } @@ -820,7 +862,7 @@ export class PartyUiHandler extends MessageUiHandler { // TODO: This risks hitting the other options (.MOVE_i and ALL) so does it? Do we need an extra check? if ( option >= PartyOption.FORM_CHANGE_ITEM && - globalScene.phaseManager.getCurrentPhase()?.is("SelectModifierPhase") && + globalScene.phaseManager.getCurrentPhase().is("SelectModifierPhase") && this.partyUiMode === PartyUiMode.CHECK ) { const formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon); @@ -1021,7 +1063,8 @@ export class PartyUiHandler extends MessageUiHandler { } // Toggle item transfer mode to discard items or vice versa - if (this.cursor === 7) { + // Prevent changing mode, when currently transfering an item + if (this.cursor === 7 && !this.transferMode) { switch (this.partyUiMode) { case PartyUiMode.DISCARD: this.partyUiMode = PartyUiMode.MODIFIER_TRANSFER; @@ -1513,7 +1556,7 @@ export class PartyUiHandler extends MessageUiHandler { break; case PartyUiMode.CHECK: this.addCommonOptions(pokemon); - if (globalScene.phaseManager.getCurrentPhase()?.is("SelectModifierPhase")) { + if (globalScene.phaseManager.getCurrentPhase().is("SelectModifierPhase")) { const formChangeItemModifiers = this.getFormChangeItemsModifiers(pokemon); for (let i = 0; i < formChangeItemModifiers.length; i++) { this.options.push(PartyOption.FORM_CHANGE_ITEM + i); @@ -1609,7 +1652,7 @@ export class PartyUiHandler extends MessageUiHandler { const modifier = formChangeItemModifiers[option - PartyOption.FORM_CHANGE_ITEM]; optionName = `${modifier.active ? i18next.t("partyUiHandler:deactivate") : i18next.t("partyUiHandler:activate")} ${modifier.type.name}`; } else if (option === PartyOption.UNPAUSE_EVOLUTION) { - optionName = `${pokemon.pauseEvolutions ? i18next.t("partyUiHandler:unpausedEvolution") : i18next.t("partyUiHandler:pauseEvolution")}`; + optionName = `${pokemon.pauseEvolutions ? i18next.t("partyUiHandler:unpauseEvolution") : i18next.t("partyUiHandler:pauseEvolution")}`; } else { if (this.localizedOptions.includes(option)) { optionName = i18next.t(`partyUiHandler:${toCamelCase(PartyOption[option])}`); @@ -1630,6 +1673,8 @@ export class PartyUiHandler extends MessageUiHandler { .find(plm => plm[1] === move); } else if (option === PartyOption.ALL) { optionName = i18next.t("partyUiHandler:all"); + // add the number of items to the `all` option + optionName += ` (${this.getTransferrableItemsFromPokemon(pokemon).length})`; } else { const itemModifiers = this.getItemModifiers(pokemon); const itemModifier = itemModifiers[option]; @@ -2040,12 +2085,13 @@ class PartySlot extends Phaser.GameObjects.Container { if (this.pokemon.isShiny()) { const doubleShiny = this.pokemon.isDoubleShiny(false); + const largeIconTint = doubleShiny ? this.pokemon.getBaseVariant() : this.pokemon.getVariant(); const shinyStar = globalScene.add .image(0, 0, `shiny_star_small${doubleShiny ? "_1" : ""}`) .setOrigin(0) .setPositionRelative(this.slotName, shinyIconToNameOffset.x, shinyIconToNameOffset.y) - .setTint(getVariantTint(this.pokemon.getBaseVariant())); + .setTint(getVariantTint(largeIconTint)); slotInfoContainer.add(shinyStar); if (doubleShiny) { diff --git a/src/ui/pokedex-page-ui-handler.ts b/src/ui/pokedex-page-ui-handler.ts index 706f139b8bb..672968bd953 100644 --- a/src/ui/pokedex-page-ui-handler.ts +++ b/src/ui/pokedex-page-ui-handler.ts @@ -175,6 +175,7 @@ enum MenuOptions { export class PokedexPageUiHandler extends MessageUiHandler { private starterSelectContainer: Phaser.GameObjects.Container; private shinyOverlay: Phaser.GameObjects.Image; + private starterDexNoLabel: Phaser.GameObjects.Image; private pokemonNumberText: Phaser.GameObjects.Text; private pokemonSprite: Phaser.GameObjects.Sprite; private pokemonNameText: Phaser.GameObjects.Text; @@ -324,8 +325,12 @@ export class PokedexPageUiHandler extends MessageUiHandler { }); this.starterSelectContainer.add(this.pokemonSprite); - this.shinyOverlay = globalScene.add.image(6, 6, "summary_overlay_shiny"); - this.shinyOverlay.setOrigin(0, 0); + this.starterDexNoLabel = globalScene.add.image(6, 14, getLocalizedSpriteKey("summary_dexnb_label")); // Pixel text 'No' + this.starterDexNoLabel.setOrigin(0, 1); + this.starterSelectContainer.add(this.starterDexNoLabel); + + this.shinyOverlay = globalScene.add.image(6, 111, getLocalizedSpriteKey("summary_dexnb_label_overlay_shiny")); // Pixel text 'No' shiny + this.shinyOverlay.setOrigin(0, 1); this.shinyOverlay.setVisible(false); this.starterSelectContainer.add(this.shinyOverlay); @@ -657,7 +662,7 @@ export class PokedexPageUiHandler extends MessageUiHandler { i18next.t("pokedexUiHandler:showEvolutions"), ]; - this.scale = getTextStyleOptions(TextStyle.WINDOW, globalScene.uiTheme).scale; + this.scale = getTextStyleOptions(TextStyle.WINDOW).scale; this.menuBg = addWindow( globalScene.scaledCanvas.width - 83, 0, @@ -705,7 +710,7 @@ export class PokedexPageUiHandler extends MessageUiHandler { show(args: any[]): boolean { // Allow the use of candies if we are in one of the whitelisted phases this.canUseCandies = ["TitlePhase", "SelectStarterPhase", "CommandPhase"].includes( - globalScene.phaseManager.getCurrentPhase()?.phaseName ?? "", + globalScene.phaseManager.getCurrentPhase().phaseName, ); if (args.length >= 1 && args[0] === "refresh") { @@ -762,16 +767,8 @@ export class PokedexPageUiHandler extends MessageUiHandler { !isSeen || (!isStarterCaught && (o === MenuOptions.TOGGLE_IVS || o === MenuOptions.NATURES)) || (this.tmMoves.length < 1 && o === MenuOptions.TM_MOVES); - const color = getTextColor( - isDark ? TextStyle.SHADOW_TEXT : TextStyle.SETTINGS_VALUE, - false, - globalScene.uiTheme, - ); - const shadow = getTextColor( - isDark ? TextStyle.SHADOW_TEXT : TextStyle.SETTINGS_VALUE, - true, - globalScene.uiTheme, - ); + const color = getTextColor(isDark ? TextStyle.SHADOW_TEXT : TextStyle.SETTINGS_VALUE, false); + const shadow = getTextColor(isDark ? TextStyle.SHADOW_TEXT : TextStyle.SETTINGS_VALUE, true); return `[shadow=${shadow}][color=${color}]${label}[/color][/shadow]`; }) .join("\n"); @@ -1784,7 +1781,7 @@ export class PokedexPageUiHandler extends MessageUiHandler { options: natures .map((n: Nature, _i: number) => { const option: OptionSelectItem = { - label: getNatureName(n, true, true, true, globalScene.uiTheme), + label: getNatureName(n, true, true, true), handler: () => { return false; }, @@ -2512,10 +2509,10 @@ export class PokedexPageUiHandler extends MessageUiHandler { this.shinyOverlay.setVisible(shiny ?? false); // TODO: is false the correct default? this.pokemonNumberText.setColor( - this.getTextColor(shiny ? TextStyle.SUMMARY_DEX_NUM_GOLD : TextStyle.SUMMARY_DEX_NUM, false), + getTextColor(shiny ? TextStyle.SUMMARY_DEX_NUM_GOLD : TextStyle.SUMMARY_DEX_NUM, false), ); this.pokemonNumberText.setShadowColor( - this.getTextColor(shiny ? TextStyle.SUMMARY_DEX_NUM_GOLD : TextStyle.SUMMARY_DEX_NUM, true), + getTextColor(shiny ? TextStyle.SUMMARY_DEX_NUM_GOLD : TextStyle.SUMMARY_DEX_NUM, true), ); const assetLoadCancelled = new BooleanHolder(false); @@ -2723,8 +2720,8 @@ export class PokedexPageUiHandler extends MessageUiHandler { } } else { this.shinyOverlay.setVisible(false); - this.pokemonNumberText.setColor(this.getTextColor(TextStyle.SUMMARY)); - this.pokemonNumberText.setShadowColor(this.getTextColor(TextStyle.SUMMARY, true)); + this.pokemonNumberText.setColor(getTextColor(TextStyle.SUMMARY)); + this.pokemonNumberText.setShadowColor(getTextColor(TextStyle.SUMMARY, true)); this.pokemonGenderText.setText(""); this.setTypeIcons(null, null); } diff --git a/src/ui/pokedex-ui-handler.ts b/src/ui/pokedex-ui-handler.ts index 01046bfef9c..046ca564709 100644 --- a/src/ui/pokedex-ui-handler.ts +++ b/src/ui/pokedex-ui-handler.ts @@ -28,6 +28,7 @@ import { PokemonType } from "#enums/pokemon-type"; import type { SpeciesId } from "#enums/species-id"; import { TextStyle } from "#enums/text-style"; import { UiMode } from "#enums/ui-mode"; +import { UiTheme } from "#enums/ui-theme"; import type { Variant } from "#sprites/variant"; import { getVariantIcon, getVariantTint } from "#sprites/variant"; import type { DexAttrProps, StarterAttributes } from "#system/game-data"; @@ -41,7 +42,7 @@ import { MessageUiHandler } from "#ui/message-ui-handler"; import { PokedexMonContainer } from "#ui/pokedex-mon-container"; import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-anim-handler"; import { ScrollBar } from "#ui/scroll-bar"; -import { addTextObject } from "#ui/text"; +import { addTextObject, getTextColor } from "#ui/text"; import { addWindow } from "#ui/ui-theme"; import { BooleanHolder, fixedInt, getLocalizedSpriteKey, padInt, randIntRange, rgbHexToRgba } from "#utils/common"; import type { StarterPreferences } from "#utils/data"; @@ -470,7 +471,7 @@ export class PokedexUiHandler extends MessageUiHandler { // Offset the generation filter dropdown to avoid covering the filtered pokemon this.filterBar.offsetHybridFilters(); - if (!globalScene.uiTheme) { + if (globalScene.uiTheme === UiTheme.DEFAULT) { pokemonContainerWindow.setVisible(false); } @@ -2314,8 +2315,8 @@ export class PokedexUiHandler extends MessageUiHandler { break; } if (baseStarterValue - starterValue > 0) { - starter.label.setColor(this.getTextColor(textStyle)); - starter.label.setShadowColor(this.getTextColor(textStyle, true)); + starter.label.setColor(getTextColor(textStyle)); + starter.label.setShadowColor(getTextColor(textStyle, true)); } } diff --git a/src/ui/pokemon-info-container.ts b/src/ui/pokemon-info-container.ts index 3b2349348a8..d232100ffaa 100644 --- a/src/ui/pokemon-info-container.ts +++ b/src/ui/pokemon-info-container.ts @@ -274,8 +274,8 @@ export class PokemonInfoContainer extends Phaser.GameObjects.Container { const newGender = BigInt(1 << pokemon.gender) * DexAttr.MALE; this.pokemonGenderNewText.setText("(+)"); - this.pokemonGenderNewText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, globalScene.uiTheme)); - this.pokemonGenderNewText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, globalScene.uiTheme)); + this.pokemonGenderNewText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false)); + this.pokemonGenderNewText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true)); this.pokemonGenderNewText.setVisible((newGender & caughtAttr) === BigInt(0)); } else { this.pokemonGenderNewText.setVisible(false); @@ -290,11 +290,11 @@ export class PokemonInfoContainer extends Phaser.GameObjects.Container { const newForm = BigInt(1 << pokemon.formIndex) * DexAttr.DEFAULT_FORM; if ((newForm & caughtAttr) === BigInt(0)) { - this.pokemonFormLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, globalScene.uiTheme)); - this.pokemonFormLabelText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, globalScene.uiTheme)); + this.pokemonFormLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false)); + this.pokemonFormLabelText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true)); } else { - this.pokemonFormLabelText.setColor(getTextColor(TextStyle.WINDOW, false, globalScene.uiTheme)); - this.pokemonFormLabelText.setShadowColor(getTextColor(TextStyle.WINDOW, true, globalScene.uiTheme)); + this.pokemonFormLabelText.setColor(getTextColor(TextStyle.WINDOW, false)); + this.pokemonFormLabelText.setShadowColor(getTextColor(TextStyle.WINDOW, true)); } this.pokemonFormText.setText( @@ -320,31 +320,31 @@ export class PokemonInfoContainer extends Phaser.GameObjects.Container { const abilityTextStyle = pokemon.abilityIndex === 2 ? TextStyle.MONEY : TextStyle.WINDOW; this.pokemonAbilityText.setText(pokemon.getAbility(true).name); - this.pokemonAbilityText.setColor(getTextColor(abilityTextStyle, false, globalScene.uiTheme)); - this.pokemonAbilityText.setShadowColor(getTextColor(abilityTextStyle, true, globalScene.uiTheme)); + this.pokemonAbilityText.setColor(getTextColor(abilityTextStyle, false)); + this.pokemonAbilityText.setShadowColor(getTextColor(abilityTextStyle, true)); // Check if the player owns ability for the root form const playerOwnsThisAbility = pokemon.checkIfPlayerHasAbilityOfStarter(starterEntry.abilityAttr); if (!playerOwnsThisAbility) { - this.pokemonAbilityLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, globalScene.uiTheme)); - this.pokemonAbilityLabelText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, globalScene.uiTheme)); + this.pokemonAbilityLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false)); + this.pokemonAbilityLabelText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true)); } else { - this.pokemonAbilityLabelText.setColor(getTextColor(TextStyle.WINDOW, false, globalScene.uiTheme)); - this.pokemonAbilityLabelText.setShadowColor(getTextColor(TextStyle.WINDOW, true, globalScene.uiTheme)); + this.pokemonAbilityLabelText.setColor(getTextColor(TextStyle.WINDOW, false)); + this.pokemonAbilityLabelText.setShadowColor(getTextColor(TextStyle.WINDOW, true)); } - this.pokemonNatureText.setText(getNatureName(pokemon.getNature(), true, false, false, globalScene.uiTheme)); + this.pokemonNatureText.setText(getNatureName(pokemon.getNature(), true, false, false)); const dexNatures = dexEntry.natureAttr; const newNature = 1 << (pokemon.nature + 1); if (!(dexNatures & newNature)) { - this.pokemonNatureLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, globalScene.uiTheme)); - this.pokemonNatureLabelText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, globalScene.uiTheme)); + this.pokemonNatureLabelText.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false)); + this.pokemonNatureLabelText.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true)); } else { - this.pokemonNatureLabelText.setColor(getTextColor(TextStyle.WINDOW, false, globalScene.uiTheme)); - this.pokemonNatureLabelText.setShadowColor(getTextColor(TextStyle.WINDOW, true, globalScene.uiTheme)); + this.pokemonNatureLabelText.setColor(getTextColor(TextStyle.WINDOW, false)); + this.pokemonNatureLabelText.setShadowColor(getTextColor(TextStyle.WINDOW, true)); } const isFusion = pokemon.isFusion(); @@ -373,16 +373,16 @@ export class PokemonInfoContainer extends Phaser.GameObjects.Container { const newVariant = BigInt(1 << (pokemon.variant + 4)); this.pokemonShinyNewIcon.setText("(+)"); - this.pokemonShinyNewIcon.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, globalScene.uiTheme)); - this.pokemonShinyNewIcon.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, globalScene.uiTheme)); + this.pokemonShinyNewIcon.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false)); + this.pokemonShinyNewIcon.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true)); const newShinyOrVariant = (newShiny & caughtAttr) === BigInt(0) || (newVariant & caughtAttr) === BigInt(0); this.pokemonShinyNewIcon.setVisible(!!newShinyOrVariant); } else if ((caughtAttr & DexAttr.NON_SHINY) === BigInt(0) && (caughtAttr & DexAttr.SHINY) === DexAttr.SHINY) { //If the player has *only* caught any shiny variant of this species, not a non-shiny this.pokemonShinyNewIcon.setVisible(true); this.pokemonShinyNewIcon.setText("(+)"); - this.pokemonShinyNewIcon.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false, globalScene.uiTheme)); - this.pokemonShinyNewIcon.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true, globalScene.uiTheme)); + this.pokemonShinyNewIcon.setColor(getTextColor(TextStyle.SUMMARY_BLUE, false)); + this.pokemonShinyNewIcon.setShadowColor(getTextColor(TextStyle.SUMMARY_BLUE, true)); } else { this.pokemonShinyNewIcon.setVisible(false); } diff --git a/src/ui/run-info-ui-handler.ts b/src/ui/run-info-ui-handler.ts index 5fc0f37c72d..8b2190c3b4a 100644 --- a/src/ui/run-info-ui-handler.ts +++ b/src/ui/run-info-ui-handler.ts @@ -618,7 +618,7 @@ export class RunInfoUiHandler extends UiHandler { const runTime = getPlayTimeString(this.runInfo.playTime); runInfoText.appendText(`${i18next.t("runHistory:runLength")}: ${runTime}`, false); const runMoney = formatMoney(globalScene.moneyFormat, this.runInfo.money); - const moneyTextColor = getTextColor(TextStyle.MONEY_WINDOW, false, globalScene.uiTheme); + const moneyTextColor = getTextColor(TextStyle.MONEY_WINDOW, false); runInfoText.appendText( `[color=${moneyTextColor}]${i18next.t("battleScene:moneyOwned", { formattedMoney: runMoney })}[/color]`, ); diff --git a/src/ui/save-slot-select-ui-handler.ts b/src/ui/save-slot-select-ui-handler.ts index e9f9c5a0038..97cd3016479 100644 --- a/src/ui/save-slot-select-ui-handler.ts +++ b/src/ui/save-slot-select-ui-handler.ts @@ -181,7 +181,7 @@ export class SaveSlotSelectUiHandler extends MessageUiHandler { ui.setOverlayMode( UiMode.CONFIRM, () => { - globalScene.gameData.tryClearSession(cursor).then(response => { + globalScene.gameData.deleteSession(cursor).then(response => { if (response[0] === false) { globalScene.reset(true); } else { diff --git a/src/ui/settings/abstract-binding-ui-handler.ts b/src/ui/settings/abstract-binding-ui-handler.ts index 2c8d0eb63ba..6b747a10d2b 100644 --- a/src/ui/settings/abstract-binding-ui-handler.ts +++ b/src/ui/settings/abstract-binding-ui-handler.ts @@ -3,7 +3,7 @@ import { Button } from "#enums/buttons"; import { TextStyle } from "#enums/text-style"; import type { UiMode } from "#enums/ui-mode"; import { NavigationManager } from "#ui/navigation-menu"; -import { addTextObject } from "#ui/text"; +import { addTextObject, getTextColor } from "#ui/text"; import { UiHandler } from "#ui/ui-handler"; import { addWindow } from "#ui/ui-theme"; import i18next from "i18next"; @@ -222,16 +222,16 @@ export abstract class AbstractBindingUiHandler extends UiHandler { setCursor(cursor: number): boolean { this.cursor = cursor; if (cursor === 1) { - this.actionLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED)); - this.actionLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_SELECTED, true)); - this.cancelLabel.setColor(this.getTextColor(TextStyle.WINDOW)); - this.cancelLabel.setShadowColor(this.getTextColor(TextStyle.WINDOW, true)); + this.actionLabel.setColor(getTextColor(TextStyle.SETTINGS_SELECTED)); + this.actionLabel.setShadowColor(getTextColor(TextStyle.SETTINGS_SELECTED, true)); + this.cancelLabel.setColor(getTextColor(TextStyle.WINDOW)); + this.cancelLabel.setShadowColor(getTextColor(TextStyle.WINDOW, true)); return true; } - this.actionLabel.setColor(this.getTextColor(TextStyle.WINDOW)); - this.actionLabel.setShadowColor(this.getTextColor(TextStyle.WINDOW, true)); - this.cancelLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED)); - this.cancelLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_SELECTED, true)); + this.actionLabel.setColor(getTextColor(TextStyle.WINDOW)); + this.actionLabel.setShadowColor(getTextColor(TextStyle.WINDOW, true)); + this.cancelLabel.setColor(getTextColor(TextStyle.SETTINGS_SELECTED)); + this.cancelLabel.setShadowColor(getTextColor(TextStyle.SETTINGS_SELECTED, true)); return true; } diff --git a/src/ui/settings/abstract-control-settings-ui-handler.ts b/src/ui/settings/abstract-control-settings-ui-handler.ts index b40676fc97c..c08f1570b75 100644 --- a/src/ui/settings/abstract-control-settings-ui-handler.ts +++ b/src/ui/settings/abstract-control-settings-ui-handler.ts @@ -7,7 +7,7 @@ import type { UiMode } from "#enums/ui-mode"; import { getIconWithSettingName } from "#inputs/config-handler"; import { NavigationManager, NavigationMenu } from "#ui/navigation-menu"; import { ScrollBar } from "#ui/scroll-bar"; -import { addTextObject } from "#ui/text"; +import { addTextObject, getTextColor } from "#ui/text"; import { UiHandler } from "#ui/ui-handler"; import { addWindow } from "#ui/ui-theme"; import { toCamelCase } from "#utils/strings"; @@ -653,16 +653,16 @@ export abstract class AbstractControlSettingsUiHandler extends UiHandler { if (!this.bindingSettings.includes(setting) && !setting.includes("BUTTON_")) { // Get the label of the last selected option and revert its color to the default. const lastValueLabel = this.optionValueLabels[settingIndex][lastCursor]; - lastValueLabel.setColor(this.getTextColor(TextStyle.WINDOW)); - lastValueLabel.setShadowColor(this.getTextColor(TextStyle.WINDOW, true)); + lastValueLabel.setColor(getTextColor(TextStyle.WINDOW)); + lastValueLabel.setShadowColor(getTextColor(TextStyle.WINDOW, true)); // Update the cursor for the setting to the new position. this.optionCursors[settingIndex] = cursor; // Change the color of the new selected option to indicate it's selected. const newValueLabel = this.optionValueLabels[settingIndex][cursor]; - newValueLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED)); - newValueLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_SELECTED, true)); + newValueLabel.setColor(getTextColor(TextStyle.SETTINGS_SELECTED)); + newValueLabel.setShadowColor(getTextColor(TextStyle.SETTINGS_SELECTED, true)); } // If the save flag is set, save the setting to local storage diff --git a/src/ui/settings/abstract-settings-ui-handler.ts b/src/ui/settings/abstract-settings-ui-handler.ts index 91d5aec984a..ae1bb40dbeb 100644 --- a/src/ui/settings/abstract-settings-ui-handler.ts +++ b/src/ui/settings/abstract-settings-ui-handler.ts @@ -8,7 +8,7 @@ import type { InputsIcons } from "#ui/abstract-control-settings-ui-handler"; import { MessageUiHandler } from "#ui/message-ui-handler"; import { NavigationManager, NavigationMenu } from "#ui/navigation-menu"; import { ScrollBar } from "#ui/scroll-bar"; -import { addTextObject } from "#ui/text"; +import { addTextObject, getTextColor } from "#ui/text"; import { addWindow } from "#ui/ui-theme"; import i18next from "i18next"; @@ -403,14 +403,14 @@ export class AbstractSettingsUiHandler extends MessageUiHandler { const lastCursor = this.optionCursors[settingIndex]; const lastValueLabel = this.optionValueLabels[settingIndex][lastCursor]; - lastValueLabel.setColor(this.getTextColor(TextStyle.SETTINGS_VALUE)); - lastValueLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_VALUE, true)); + lastValueLabel.setColor(getTextColor(TextStyle.SETTINGS_VALUE)); + lastValueLabel.setShadowColor(getTextColor(TextStyle.SETTINGS_VALUE, true)); this.optionCursors[settingIndex] = cursor; const newValueLabel = this.optionValueLabels[settingIndex][cursor]; - newValueLabel.setColor(this.getTextColor(TextStyle.SETTINGS_SELECTED)); - newValueLabel.setShadowColor(this.getTextColor(TextStyle.SETTINGS_SELECTED, true)); + newValueLabel.setColor(getTextColor(TextStyle.SETTINGS_SELECTED)); + newValueLabel.setShadowColor(getTextColor(TextStyle.SETTINGS_SELECTED, true)); if (save) { const saveSetting = () => { diff --git a/src/ui/starter-select-ui-handler.ts b/src/ui/starter-select-ui-handler.ts index 25d5277b4c2..3b4b2716369 100644 --- a/src/ui/starter-select-ui-handler.ts +++ b/src/ui/starter-select-ui-handler.ts @@ -40,6 +40,7 @@ import { PokemonType } from "#enums/pokemon-type"; import { SpeciesId } from "#enums/species-id"; import { TextStyle } from "#enums/text-style"; import { UiMode } from "#enums/ui-mode"; +import { UiTheme } from "#enums/ui-theme"; import type { CandyUpgradeNotificationChangedEvent } from "#events/battle-scene"; import { BattleSceneEventType } from "#events/battle-scene"; import type { Variant } from "#sprites/variant"; @@ -58,7 +59,7 @@ import { PokemonIconAnimHandler, PokemonIconAnimMode } from "#ui/pokemon-icon-an import { ScrollBar } from "#ui/scroll-bar"; import { StarterContainer } from "#ui/starter-container"; import { StatsContainer } from "#ui/stats-container"; -import { addBBCodeTextObject, addTextObject } from "#ui/text"; +import { addBBCodeTextObject, addTextObject, getTextColor } from "#ui/text"; import { addWindow } from "#ui/ui-theme"; import { applyChallenges, checkStarterValidForChallenge } from "#utils/challenge-utils"; import { @@ -72,7 +73,7 @@ import { rgbHexToRgba, } from "#utils/common"; import type { StarterPreferences } from "#utils/data"; -import { loadStarterPreferences, saveStarterPreferences } from "#utils/data"; +import { deepCopy, loadStarterPreferences, saveStarterPreferences } from "#utils/data"; import { getPokemonSpeciesForm, getPokerusStarters } from "#utils/pokemon-utils"; import { toCamelCase, toTitleCase } from "#utils/strings"; import { argbFromRgba } from "@material/material-color-utilities"; @@ -339,7 +340,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { private teraLabel: Phaser.GameObjects.Text; private goFilterLabel: Phaser.GameObjects.Text; /** Group holding the UI elements appearing in the instructionsContainer */ - /* TODO: Uncomment this once our testing infra supports mocks of `Phaser.GameObject.Group` + /* TODO: Uncomment this once our testing infra supports mocks of `Phaser.GameObject.Group` private instructionElemGroup: Phaser.GameObjects.Group; */ @@ -432,8 +433,15 @@ export class StarterSelectUiHandler extends MessageUiHandler { const bgColor = globalScene.add.rectangle(0, 0, sWidth, sHeight, 0x006860).setOrigin(0); + const starterDexNoLabel = globalScene.add + .image(6, 14, getLocalizedSpriteKey("summary_dexnb_label")) + .setOrigin(0, 1); // Pixel text 'No' + const starterSelectBg = globalScene.add.image(0, 0, "starter_select_bg").setOrigin(0); - this.shinyOverlay = globalScene.add.image(6, 6, "summary_overlay_shiny").setOrigin(0).setVisible(false); + this.shinyOverlay = globalScene.add + .image(6, 111, getLocalizedSpriteKey("summary_dexnb_label_overlay_shiny")) + .setOrigin(0, 1) + .setVisible(false); // Pixel text 'No' shiny const starterContainerWindow = addWindow(speciesContainerX, filterBarHeight + 1, 175, 161); const starterContainerBg = globalScene.add @@ -592,7 +600,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { // Offset the generation filter dropdown to avoid covering the filtered pokemon this.filterBar.offsetHybridFilters(); - if (!globalScene.uiTheme) { + if (globalScene.uiTheme === UiTheme.DEFAULT) { starterContainerWindow.setVisible(false); } @@ -1070,6 +1078,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.starterSelectContainer.add([ bgColor, starterSelectBg, + starterDexNoLabel, this.shinyOverlay, starterContainerBg, addWindow( @@ -1148,7 +1157,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.starterSelectContainer.setVisible(true); this.starterPreferences = loadStarterPreferences(); - this.originalStarterPreferences = loadStarterPreferences(); + // Deep copy the JSON (avoid re-loading from disk) + this.originalStarterPreferences = deepCopy(this.starterPreferences); this.allSpecies.forEach((species, s) => { const icon = this.starterContainers[s].icon; @@ -1212,6 +1222,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { preferences: StarterPreferences, ignoreChallenge = false, ): StarterAttributes { + // if preferences for the species is undefined, set it to an empty object + preferences[species.speciesId] ??= {}; const starterAttributes = preferences[species.speciesId]; const { dexEntry, starterDataEntry: starterData } = this.getSpeciesData(species.speciesId, !ignoreChallenge); @@ -1607,6 +1619,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { if (!this.filterMode) { this.startCursorObj.setVisible(false); this.starterIconsCursorObj.setVisible(false); + this.randomCursorObj.setVisible(false); this.setSpecies(null); this.filterBarCursor = 0; this.setFilterMode(true); @@ -1828,9 +1841,15 @@ export class StarterSelectUiHandler extends MessageUiHandler { // 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]; + if (this.starterPreferences[this.lastSpecies.speciesId] === undefined) { + this.starterPreferences[this.lastSpecies.speciesId] = {}; + } + if (this.originalStarterPreferences[this.lastSpecies.speciesId] === undefined) { + this.originalStarterPreferences[this.lastSpecies.speciesId] = {}; + } + // Bangs are safe here due to the above check + const starterAttributes = this.starterPreferences[this.lastSpecies.speciesId]!; + 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) { @@ -2048,12 +2067,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { options: natures .map((n: Nature, _i: number) => { const option: OptionSelectItem = { - label: getNatureName(n, true, true, true, globalScene.uiTheme), + label: getNatureName(n, true, true, true), handler: () => { - // update default nature in starter save data - if (!starterAttributes) { - starterAttributes = this.starterPreferences[this.lastSpecies.speciesId] = {}; - } starterAttributes.nature = n; originalStarterAttributes.nature = starterAttributes.nature; this.clearText(); @@ -2095,27 +2110,21 @@ export class StarterSelectUiHandler extends MessageUiHandler { const passiveAttr = starterData.passiveAttr; if (passiveAttr & PassiveAttr.UNLOCKED) { // this is for enabling and disabling the passive - if (!(passiveAttr & PassiveAttr.ENABLED)) { - options.push({ - label: i18next.t("starterSelectUiHandler:enablePassive"), - handler: () => { - starterData.passiveAttr |= PassiveAttr.ENABLED; - ui.setMode(UiMode.STARTER_SELECT); - this.setSpeciesDetails(this.lastSpecies); - return true; - }, - }); - } else { - options.push({ - label: i18next.t("starterSelectUiHandler:disablePassive"), - handler: () => { - starterData.passiveAttr ^= PassiveAttr.ENABLED; - ui.setMode(UiMode.STARTER_SELECT); - this.setSpeciesDetails(this.lastSpecies); - return true; - }, - }); - } + const label = i18next.t( + passiveAttr & PassiveAttr.ENABLED + ? "starterSelectUiHandler:disablePassive" + : "starterSelectUiHandler:enablePassive", + ); + options.push({ + label, + handler: () => { + starterData.passiveAttr ^= PassiveAttr.ENABLED; + persistentStarterData.passiveAttr ^= PassiveAttr.ENABLED; + ui.setMode(UiMode.STARTER_SELECT); + this.setSpeciesDetails(this.lastSpecies); + return true; + }, + }); } // if container.favorite is false, show the favorite option const isFavorite = starterAttributes?.favorite ?? false; @@ -3414,8 +3423,9 @@ export class StarterSelectUiHandler extends MessageUiHandler { if (species) { const defaultDexAttr = this.getCurrentDexProps(species.speciesId); const defaultProps = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); + // Bang is correct due to the `?` before variant const variant = this.starterPreferences[species.speciesId]?.variant - ? (this.starterPreferences[species.speciesId].variant as Variant) + ? (this.starterPreferences[species.speciesId]!.variant as Variant) : defaultProps.variant; const tint = getVariantTint(variant); this.pokemonShinyIcon.setFrame(getVariantIcon(variant)).setTint(tint); @@ -3640,15 +3650,19 @@ export class StarterSelectUiHandler extends MessageUiHandler { if (starterIndex > -1) { props = globalScene.gameData.getSpeciesDexAttrProps(species, this.starterAttr[starterIndex]); - this.setSpeciesDetails(species, { - shiny: props.shiny, - formIndex: props.formIndex, - female: props.female, - variant: props.variant, - abilityIndex: this.starterAbilityIndexes[starterIndex], - natureIndex: this.starterNatures[starterIndex], - teraType: this.starterTeras[starterIndex], - }); + this.setSpeciesDetails( + species, + { + shiny: props.shiny, + formIndex: props.formIndex, + female: props.female, + variant: props.variant, + abilityIndex: this.starterAbilityIndexes[starterIndex], + natureIndex: this.starterNatures[starterIndex], + teraType: this.starterTeras[starterIndex], + }, + false, + ); } else { const defaultAbilityIndex = starterAttributes?.ability ?? globalScene.gameData.getStarterSpeciesDefaultAbilityIndex(species); @@ -3665,15 +3679,19 @@ export class StarterSelectUiHandler extends MessageUiHandler { props.formIndex = starterAttributes?.form ?? props.formIndex; props.female = starterAttributes?.female ?? props.female; - this.setSpeciesDetails(species, { - shiny: props.shiny, - formIndex: props.formIndex, - female: props.female, - variant: props.variant, - abilityIndex: defaultAbilityIndex, - natureIndex: defaultNature, - teraType: starterAttributes?.tera, - }); + this.setSpeciesDetails( + species, + { + shiny: props.shiny, + formIndex: props.formIndex, + female: props.female, + variant: props.variant, + abilityIndex: defaultAbilityIndex, + natureIndex: defaultNature, + teraType: starterAttributes?.tera, + }, + false, + ); } if (!isNullOrUndefined(props.formIndex)) { @@ -3710,15 +3728,19 @@ export class StarterSelectUiHandler extends MessageUiHandler { const defaultNature = globalScene.gameData.getSpeciesDefaultNature(species); const props = globalScene.gameData.getSpeciesDexAttrProps(species, defaultDexAttr); - this.setSpeciesDetails(species, { - shiny: props.shiny, - formIndex: props.formIndex, - female: props.female, - variant: props.variant, - abilityIndex: defaultAbilityIndex, - natureIndex: defaultNature, - forSeen: true, - }); + this.setSpeciesDetails( + species, + { + shiny: props.shiny, + formIndex: props.formIndex, + female: props.female, + variant: props.variant, + abilityIndex: defaultAbilityIndex, + natureIndex: defaultNature, + forSeen: true, + }, + false, + ); this.pokemonSprite.setTint(0x808080); } } else { @@ -3740,15 +3762,19 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.pokemonFormText.setVisible(false); this.teraIcon.setVisible(false); - this.setSpeciesDetails(species!, { - // TODO: is this bang correct? - shiny: false, - formIndex: 0, - female: false, - variant: 0, - abilityIndex: 0, - natureIndex: 0, - }); + this.setSpeciesDetails( + species!, + { + // TODO: is this bang correct? + shiny: false, + formIndex: 0, + female: false, + variant: 0, + abilityIndex: 0, + natureIndex: 0, + }, + false, + ); this.pokemonSprite.clearTint(); } } @@ -3770,7 +3796,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { return { dexEntry: { ...copiedDexEntry }, starterDataEntry: { ...copiedStarterDataEntry } }; } - setSpeciesDetails(species: PokemonSpecies, options: SpeciesDetails = {}): void { + setSpeciesDetails(species: PokemonSpecies, options: SpeciesDetails = {}, save = true): 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; @@ -3885,10 +3911,10 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.shinyOverlay.setVisible(shiny ?? false); // TODO: is false the correct default? this.pokemonNumberText.setColor( - this.getTextColor(shiny ? TextStyle.SUMMARY_DEX_NUM_GOLD : TextStyle.SUMMARY_DEX_NUM, false), + getTextColor(shiny ? TextStyle.SUMMARY_DEX_NUM_GOLD : TextStyle.SUMMARY_DEX_NUM, false), ); this.pokemonNumberText.setShadowColor( - this.getTextColor(shiny ? TextStyle.SUMMARY_DEX_NUM_GOLD : TextStyle.SUMMARY_DEX_NUM, true), + getTextColor(shiny ? TextStyle.SUMMARY_DEX_NUM_GOLD : TextStyle.SUMMARY_DEX_NUM, true), ); if (forSeen ? this.speciesStarterDexEntry?.seenAttr : this.speciesStarterDexEntry?.caughtAttr) { @@ -3997,8 +4023,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { const isHidden = abilityIndex === (this.lastSpecies.ability2 ? 2 : 1); this.pokemonAbilityText .setText(ability.name) - .setColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD)) - .setShadowColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD, true)); + .setColor(getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD)) + .setShadowColor(getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD, true)); const passiveAttr = starterDataEntry.passiveAttr; const passiveAbility = allAbilities[this.lastSpecies.getPassiveAbility(formIndex)]; @@ -4027,14 +4053,14 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.pokemonPassiveLabelText .setVisible(!isFreshStartChallenge) - .setColor(this.getTextColor(TextStyle.SUMMARY_ALT)) - .setShadowColor(this.getTextColor(TextStyle.SUMMARY_ALT, true)); + .setColor(getTextColor(TextStyle.SUMMARY_ALT)) + .setShadowColor(getTextColor(TextStyle.SUMMARY_ALT, true)); this.pokemonPassiveText .setVisible(!isFreshStartChallenge) .setText(passiveAbility.name) - .setColor(this.getTextColor(textStyle)) + .setColor(getTextColor(textStyle)) .setAlpha(textAlpha) - .setShadowColor(this.getTextColor(textStyle, true)); + .setShadowColor(getTextColor(textStyle, true)); if (this.activeTooltip === "PASSIVE") { globalScene.ui.editTooltip(`${passiveAbility.name}`, `${passiveAbility.description}`); @@ -4066,9 +4092,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { globalScene.ui.hideTooltip(); } - this.pokemonNatureText.setText( - getNatureName(natureIndex as unknown as Nature, true, true, false, globalScene.uiTheme), - ); + this.pokemonNatureText.setText(getNatureName(natureIndex as unknown as Nature, true, true, false)); let levelMoves: LevelMoves; if ( @@ -4135,8 +4159,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { } else { this.shinyOverlay.setVisible(false); this.pokemonNumberText - .setColor(this.getTextColor(TextStyle.SUMMARY)) - .setShadowColor(this.getTextColor(TextStyle.SUMMARY, true)); + .setColor(getTextColor(TextStyle.SUMMARY)) + .setShadowColor(getTextColor(TextStyle.SUMMARY, true)); this.pokemonGenderText.setText(""); this.pokemonAbilityText.setText(""); this.pokemonPassiveText.setText(""); @@ -4182,7 +4206,9 @@ export class StarterSelectUiHandler extends MessageUiHandler { this.updateInstructions(); - saveStarterPreferences(this.originalStarterPreferences); + if (save) { + saveStarterPreferences(this.originalStarterPreferences); + } } setTypeIcons(type1: PokemonType | null, type2: PokemonType | null): void { @@ -4276,7 +4302,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { textStyle = TextStyle.SUMMARY_GOLD; break; } - starter.label.setColor(this.getTextColor(textStyle)).setShadowColor(this.getTextColor(textStyle, true)); + starter.label.setColor(getTextColor(textStyle)).setShadowColor(getTextColor(textStyle, true)); } tryUpdateValue(add?: number, addingToParty?: boolean): boolean { @@ -4296,8 +4322,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { } this.valueLimitLabel .setText(`${newValueStr}/${valueLimit}`) - .setColor(this.getTextColor(!overLimit ? TextStyle.TOOLTIP_CONTENT : TextStyle.SUMMARY_PINK)) - .setShadowColor(this.getTextColor(!overLimit ? TextStyle.TOOLTIP_CONTENT : TextStyle.SUMMARY_PINK, true)); + .setColor(getTextColor(!overLimit ? TextStyle.TOOLTIP_CONTENT : TextStyle.SUMMARY_PINK)) + .setShadowColor(getTextColor(!overLimit ? TextStyle.TOOLTIP_CONTENT : TextStyle.SUMMARY_PINK, true)); if (overLimit) { globalScene.time.delayedCall(fixedInt(500), () => this.tryUpdateValue()); return false; @@ -4394,7 +4420,7 @@ export class StarterSelectUiHandler extends MessageUiHandler { globalScene.phaseManager.pushNew("EncounterPhase"); } this.clearText(); - globalScene.phaseManager.getCurrentPhase()?.end(); + globalScene.phaseManager.getCurrentPhase().end(); }, cancel, null, @@ -4618,6 +4644,8 @@ export class StarterSelectUiHandler extends MessageUiHandler { clear(): void { super.clear(); + saveStarterPreferences(this.originalStarterPreferences); + this.clearStarterPreferences(); this.cursor = -1; this.hideInstructions(); diff --git a/src/ui/stats-container.ts b/src/ui/stats-container.ts index e9af5eed3e3..f5221d38991 100644 --- a/src/ui/stats-container.ts +++ b/src/ui/stats-container.ts @@ -113,7 +113,7 @@ export class StatsContainer extends Phaser.GameObjects.Container { (ivs[ivChartStatIndexes[i]] / 31) * ivChartSize * ivChartStatCoordMultipliers[ivChartStatIndexes[i]][1], ]); const lastIvChartData = this.statsIvsCache || defaultIvChartData; - const perfectIVColor: string = getTextColor(TextStyle.SUMMARY_GOLD, false, globalScene.uiTheme); + const perfectIVColor: string = getTextColor(TextStyle.SUMMARY_GOLD, false); this.statsIvsCache = ivChartData.slice(0); this.ivStatValueTexts.map((t: BBCodeText, i: number) => { @@ -127,7 +127,7 @@ export class StatsContainer extends Phaser.GameObjects.Container { } if (this.showDiff && originalIvs) { if (originalIvs[i] < ivs[i]) { - label += ` ([color=${getTextColor(TextStyle.SUMMARY_BLUE, false, globalScene.uiTheme)}][shadow=${getTextColor(TextStyle.SUMMARY_BLUE, true, globalScene.uiTheme)}]+${ivs[i] - originalIvs[i]}[/shadow][/color])`; + label += ` ([color=${getTextColor(TextStyle.SUMMARY_BLUE, false)}][shadow=${getTextColor(TextStyle.SUMMARY_BLUE, true)}]+${ivs[i] - originalIvs[i]}[/shadow][/color])`; } else { label += " (-)"; } diff --git a/src/ui/summary-ui-handler.ts b/src/ui/summary-ui-handler.ts index b6447f03587..f737411896e 100644 --- a/src/ui/summary-ui-handler.ts +++ b/src/ui/summary-ui-handler.ts @@ -25,7 +25,7 @@ import type { PokemonMove } from "#moves/pokemon-move"; import type { Variant } from "#sprites/variant"; import { getVariantTint } from "#sprites/variant"; import { achvs } from "#system/achv"; -import { addBBCodeTextObject, addTextObject, getBBCodeFrag } from "#ui/text"; +import { addBBCodeTextObject, addTextObject, getBBCodeFrag, getTextColor } from "#ui/text"; import { UiHandler } from "#ui/ui-handler"; import { fixedInt, @@ -68,6 +68,7 @@ export class SummaryUiHandler extends UiHandler { private summaryUiMode: SummaryUiMode; private summaryContainer: Phaser.GameObjects.Container; + private summaryContainerDexNoLabel: Phaser.GameObjects.Image; private tabSprite: Phaser.GameObjects.Sprite; private shinyOverlay: Phaser.GameObjects.Image; private numberText: Phaser.GameObjects.Text; @@ -94,12 +95,15 @@ export class SummaryUiHandler extends UiHandler { private passiveContainer: abilityContainer; private summaryPageContainer: Phaser.GameObjects.Container; private movesContainer: Phaser.GameObjects.Container; + private movesContainerMovesTitle: Phaser.GameObjects.Image; + private movesContainerDescriptionsTitle: Phaser.GameObjects.Image; private moveDescriptionText: Phaser.GameObjects.Text; private moveCursorObj: Phaser.GameObjects.Sprite | null; private selectedMoveCursorObj: Phaser.GameObjects.Sprite | null; private moveRowsContainer: Phaser.GameObjects.Container; private extraMoveRowContainer: Phaser.GameObjects.Container; private moveEffectContainer: Phaser.GameObjects.Container; + private moveEffectContainerTitle: Phaser.GameObjects.Image; private movePowerText: Phaser.GameObjects.Text; private moveAccuracyText: Phaser.GameObjects.Text; private moveCategoryIcon: Phaser.GameObjects.Sprite; @@ -111,6 +115,10 @@ export class SummaryUiHandler extends UiHandler { private permStatsContainer: Phaser.GameObjects.Container; private ivContainer: Phaser.GameObjects.Container; private statsContainer: Phaser.GameObjects.Container; + private statsContainerItemTitle: Phaser.GameObjects.Image; + private statsContainerStatsTitle: Phaser.GameObjects.Image; + private statsContainerExpTitle: Phaser.GameObjects.Image; + private statsContainerExpBarTitle: Phaser.GameObjects.Image; private descriptionScrollTween: Phaser.Tweens.Tween | null; private moveCursorBlinkTimer: Phaser.Time.TimerEvent | null; @@ -144,15 +152,19 @@ export class SummaryUiHandler extends UiHandler { summaryBg.setOrigin(0, 1); this.summaryContainer.add(summaryBg); - this.tabSprite = globalScene.add.sprite(134, -summaryBg.displayHeight + 16, "summary_tabs_1"); - this.tabSprite.setOrigin(1, 1); + this.tabSprite = globalScene.add.sprite(81, -summaryBg.displayHeight + 16, getLocalizedSpriteKey("summary_tabs_1")); // Pixel text 'STATUS' tab + this.tabSprite.setOrigin(0, 1); this.summaryContainer.add(this.tabSprite); const summaryLabel = addTextObject(4, -165, i18next.t("pokemonSummary:pokemonInfo"), TextStyle.SUMMARY_HEADER); summaryLabel.setOrigin(0, 1); this.summaryContainer.add(summaryLabel); - this.shinyOverlay = globalScene.add.image(6, -54, "summary_overlay_shiny"); + this.summaryContainerDexNoLabel = globalScene.add.image(6, -151, getLocalizedSpriteKey("summary_dexnb_label")); // Pixel text 'No' + this.summaryContainerDexNoLabel.setOrigin(0, 1); + this.summaryContainer.add(this.summaryContainerDexNoLabel); + + this.shinyOverlay = globalScene.add.image(6, -54, getLocalizedSpriteKey("summary_dexnb_label_overlay_shiny")); // Pixel text 'No' shiny this.shinyOverlay.setOrigin(0, 1); this.shinyOverlay.setVisible(false); this.summaryContainer.add(this.shinyOverlay); @@ -281,6 +293,10 @@ export class SummaryUiHandler extends UiHandler { moveEffectBg.setOrigin(0, 0); this.moveEffectContainer.add(moveEffectBg); + this.moveEffectContainerTitle = globalScene.add.image(7, 7, getLocalizedSpriteKey("summary_moves_effect_title")); // Pixel text 'EFFECT' + this.moveEffectContainerTitle.setOrigin(0, 0.5); + this.moveEffectContainer.add(this.moveEffectContainerTitle); + const moveEffectLabels = addTextObject(8, 12, i18next.t("pokemonSummary:powerAccuracyCategory"), TextStyle.SUMMARY); moveEffectLabels.setLineSpacing(9); moveEffectLabels.setOrigin(0, 0); @@ -345,9 +361,9 @@ export class SummaryUiHandler extends UiHandler { this.candyOverlay.setTint(argbFromRgba(rgbHexToRgba(colorScheme[1]))); this.numberText.setText(padInt(this.pokemon.species.speciesId, 4)); - this.numberText.setColor(this.getTextColor(!this.pokemon.isShiny() ? TextStyle.SUMMARY : TextStyle.SUMMARY_GOLD)); + this.numberText.setColor(getTextColor(!this.pokemon.isShiny() ? TextStyle.SUMMARY : TextStyle.SUMMARY_GOLD)); this.numberText.setShadowColor( - this.getTextColor(!this.pokemon.isShiny() ? TextStyle.SUMMARY : TextStyle.SUMMARY_GOLD, true), + getTextColor(!this.pokemon.isShiny() ? TextStyle.SUMMARY : TextStyle.SUMMARY_GOLD, true), ); const spriteKey = this.pokemon.getSpriteKey(true); try { @@ -430,20 +446,21 @@ export class SummaryUiHandler extends UiHandler { this.friendshipShadow.setCrop(0, 0, 16, 16 - 16 * ((this.pokemon?.friendship || 0) / 255)); const doubleShiny = this.pokemon.isDoubleShiny(false); - const baseVariant = this.pokemon.getBaseVariant(doubleShiny); + const bigIconVariant = doubleShiny ? this.pokemon.getBaseVariant(doubleShiny) : this.pokemon.getVariant(); this.shinyIcon.setPositionRelative( this.nameText, this.nameText.displayWidth + (this.splicedIcon.visible ? this.splicedIcon.displayWidth + 1 : 0) + 1, 3, ); - this.shinyIcon.setTexture(`shiny_star${doubleShiny ? "_1" : ""}`); - this.shinyIcon.setVisible(this.pokemon.isShiny(false)); - this.shinyIcon.setTint(getVariantTint(baseVariant)); + this.shinyIcon + .setTexture(`shiny_star${doubleShiny ? "_1" : ""}`) + .setVisible(this.pokemon.isShiny(false)) + .setTint(getVariantTint(bigIconVariant)); if (this.shinyIcon.visible) { let shinyDescriptor = ""; - if (doubleShiny || baseVariant) { - shinyDescriptor = " (" + getShinyDescriptor(baseVariant); + if (doubleShiny || bigIconVariant) { + shinyDescriptor = " (" + getShinyDescriptor(bigIconVariant); if (doubleShiny) { shinyDescriptor += "/" + getShinyDescriptor(this.pokemon.fusionVariant); } @@ -737,7 +754,7 @@ export class SummaryUiHandler extends UiHandler { const forward = this.cursor < cursor; this.cursor = cursor; - this.tabSprite.setTexture(`summary_tabs_${this.cursor + 1}`); + this.tabSprite.setTexture(getLocalizedSpriteKey(`summary_tabs_${this.cursor + 1}`)); // Pixel text 'STATUS' and "MOVES" tabs this.getUi().hideTooltip(); @@ -811,6 +828,14 @@ export class SummaryUiHandler extends UiHandler { ? i18next.t("trainerNames:playerF") : i18next.t("trainerNames:playerM"); + const profileContainerProfilTitle = globalScene.add.image( + 7, + 4, + getLocalizedSpriteKey("summary_profile_profile_title"), // Pixel text 'PROFIL' + ); + profileContainerProfilTitle.setOrigin(0, 0.5); + profileContainer.add(profileContainerProfilTitle); + // TODO: should add field for original trainer name to Pokemon object, to support gift/traded Pokemon from MEs const trainerText = addBBCodeTextObject( 7, @@ -885,7 +910,7 @@ export class SummaryUiHandler extends UiHandler { } this.abilityContainer = { - labelImage: globalScene.add.image(0, 0, "summary_profile_ability"), + labelImage: globalScene.add.image(0, 0, getLocalizedSpriteKey("summary_profile_ability")), // Pixel text 'ABILITY' ability: this.pokemon?.getAbility(true)!, // TODO: is this bang correct? nameText: null, descriptionText: null, @@ -895,7 +920,7 @@ export class SummaryUiHandler extends UiHandler { // Only add to the array and set up displaying a passive if it's unlocked if (this.pokemon?.hasPassive()) { this.passiveContainer = { - labelImage: globalScene.add.image(0, 0, "summary_profile_passive"), + labelImage: globalScene.add.image(0, 0, getLocalizedSpriteKey("summary_profile_passive")), // Pixel text 'PASSIVE' ability: this.pokemon.getPassiveAbility(), nameText: null, descriptionText: null, @@ -915,9 +940,9 @@ export class SummaryUiHandler extends UiHandler { } allAbilityInfo.forEach(abilityInfo => { - abilityInfo.labelImage.setPosition(17, 43); + abilityInfo.labelImage.setPosition(17, 47); abilityInfo.labelImage.setVisible(true); - abilityInfo.labelImage.setOrigin(0, 0); + abilityInfo.labelImage.setOrigin(0, 0.5); profileContainer.add(abilityInfo.labelImage); abilityInfo.nameText = addTextObject(7, 68, abilityInfo.ability?.name!, TextStyle.SUMMARY_ALT); // TODO: is this bang correct? @@ -965,6 +990,14 @@ export class SummaryUiHandler extends UiHandler { 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 profileContainerMemoTitle = globalScene.add.image( + 7, + 107, + getLocalizedSpriteKey("summary_profile_memo_title"), // Pixel text 'TRAINER MEMO' + ); + profileContainerMemoTitle.setOrigin(0, 0.5); + profileContainer.add(profileContainerMemoTitle); + const memoString = i18next.t("pokemonSummary:memoString", { metFragment: i18next.t( `pokemonSummary:metFragment.${this.pokemon?.metBiome === -1 ? "apparently" : "normal"}`, @@ -991,6 +1024,30 @@ export class SummaryUiHandler extends UiHandler { this.statsContainer.add(this.ivContainer); this.statsContainer.setVisible(true); + this.statsContainerItemTitle = globalScene.add.image(7, 4, getLocalizedSpriteKey("summary_stats_item_title")); // Pixel text 'ITEM' + this.statsContainerItemTitle.setOrigin(0, 0.5); + this.statsContainer.add(this.statsContainerItemTitle); + + this.statsContainerStatsTitle = globalScene.add.image( + 16, + 51, + getLocalizedSpriteKey("summary_stats_stats_title"), // Pixel text 'STATS' + ); + this.statsContainerStatsTitle.setOrigin(0, 0.5); + this.statsContainer.add(this.statsContainerStatsTitle); + + this.statsContainerExpTitle = globalScene.add.image(7, 107, getLocalizedSpriteKey("summary_stats_exp_title")); // Pixel text 'EXP.' + this.statsContainerExpTitle.setOrigin(0, 0.5); + this.statsContainer.add(this.statsContainerExpTitle); + + this.statsContainerExpBarTitle = globalScene.add.image( + 126, + 144, + getLocalizedSpriteKey("summary_stats_expbar_title"), // Pixel mini text 'EXP' + ); + this.statsContainerExpBarTitle.setOrigin(0, 0); + this.statsContainer.add(this.statsContainerExpBarTitle); + PERMANENT_STATS.forEach((stat, s) => { const statName = i18next.t(getStatKey(stat)); const rowIndex = s % 3; @@ -1106,6 +1163,22 @@ export class SummaryUiHandler extends UiHandler { this.movesContainer = globalScene.add.container(5, -pageBg.height + 26); pageContainer.add(this.movesContainer); + this.movesContainerMovesTitle = globalScene.add.image( + 2, + -22, + getLocalizedSpriteKey("summary_moves_moves_title"), + ); // Pixel text 'MOVES' + this.movesContainerMovesTitle.setOrigin(0, 0.5); + this.movesContainer.add(this.movesContainerMovesTitle); + + this.movesContainerDescriptionsTitle = globalScene.add.image( + 2, + 78, + getLocalizedSpriteKey("summary_moves_descriptions_title"), + ); // Pixel text 'DESCRIPTIONS' + this.movesContainerDescriptionsTitle.setOrigin(0, 0.5); + this.movesContainer.add(this.movesContainerDescriptionsTitle); + this.extraMoveRowContainer = globalScene.add.container(0, 64); this.extraMoveRowContainer.setVisible(false); this.movesContainer.add(this.extraMoveRowContainer); @@ -1135,8 +1208,8 @@ export class SummaryUiHandler extends UiHandler { newMoveTypeIcon.setOrigin(0, 1); this.extraMoveRowContainer.add(newMoveTypeIcon); } - const ppOverlay = globalScene.add.image(163, -1, "summary_moves_overlay_pp"); - ppOverlay.setOrigin(0, 1); + const ppOverlay = globalScene.add.image(172, -5, getLocalizedSpriteKey("summary_moves_overlay_pp")); // Pixel text 'PP' + ppOverlay.setOrigin(1, 0.5); this.extraMoveRowContainer.add(ppOverlay); const pp = padInt(this.newMove?.pp!, 2, " "); // TODO: is this bang correct? @@ -1166,8 +1239,8 @@ export class SummaryUiHandler extends UiHandler { moveText.setOrigin(0, 1); moveRowContainer.add(moveText); - const ppOverlay = globalScene.add.image(163, -1, "summary_moves_overlay_pp"); - ppOverlay.setOrigin(0, 1); + const ppOverlay = globalScene.add.image(172, -5, getLocalizedSpriteKey("summary_moves_overlay_pp")); // Pixel text 'PP' + ppOverlay.setOrigin(1, 0.5); moveRowContainer.add(ppOverlay); const ppText = addTextObject(173, 1, "--/--", TextStyle.WINDOW); diff --git a/src/ui/text.ts b/src/ui/text.ts index 8aa50983874..927f9f08bb2 100644 --- a/src/ui/text.ts +++ b/src/ui/text.ts @@ -16,11 +16,7 @@ export function addTextObject( style: TextStyle, extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle, ): Phaser.GameObjects.Text { - const { scale, styleOptions, shadowColor, shadowXpos, shadowYpos } = getTextStyleOptions( - style, - globalScene.uiTheme, - extraStyleOptions, - ); + const { scale, styleOptions, shadowColor, shadowXpos, shadowYpos } = getTextStyleOptions(style, extraStyleOptions); const ret = globalScene.add .text(x, y, content, styleOptions) @@ -38,11 +34,7 @@ export function setTextStyle( style: TextStyle, extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle, ) { - const { scale, styleOptions, shadowColor, shadowXpos, shadowYpos } = getTextStyleOptions( - style, - globalScene.uiTheme, - extraStyleOptions, - ); + const { scale, styleOptions, shadowColor, shadowXpos, shadowYpos } = getTextStyleOptions(style, extraStyleOptions); obj.setScale(scale).setShadow(shadowXpos, shadowYpos, shadowColor); if (!(styleOptions as Phaser.Types.GameObjects.Text.TextStyle).lineSpacing) { obj.setLineSpacing(scale * 30); @@ -60,11 +52,7 @@ export function addBBCodeTextObject( style: TextStyle, extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle, ): BBCodeText { - const { scale, styleOptions, shadowColor, shadowXpos, shadowYpos } = getTextStyleOptions( - style, - globalScene.uiTheme, - extraStyleOptions, - ); + const { scale, styleOptions, shadowColor, shadowXpos, shadowYpos } = getTextStyleOptions(style, extraStyleOptions); const ret = new BBCodeText(globalScene, x, y, content, styleOptions as BBCodeText.TextStyle); globalScene.add.existing(ret); @@ -84,7 +72,7 @@ export function addTextInputObject( style: TextStyle, extraStyleOptions?: InputText.IConfig, ): InputText { - const { scale, styleOptions } = getTextStyleOptions(style, globalScene.uiTheme, extraStyleOptions); + const { scale, styleOptions } = getTextStyleOptions(style, extraStyleOptions); const ret = globalScene.add.rexInputText(x, y, width, height, styleOptions as InputText.IConfig); ret.setScale(scale); @@ -94,7 +82,6 @@ export function addTextInputObject( export function getTextStyleOptions( style: TextStyle, - uiTheme: UiTheme, extraStyleOptions?: Phaser.Types.GameObjects.Text.TextStyle, ): TextStyleOptions { const lang = i18next.resolvedLanguage; @@ -106,7 +93,7 @@ export function getTextStyleOptions( let styleOptions: Phaser.Types.GameObjects.Text.TextStyle = { fontFamily: "emerald", fontSize: 96, - color: getTextColor(style, false, uiTheme), + color: getTextColor(style, false), padding: { bottom: 6, }, @@ -349,6 +336,15 @@ export function getTextStyleOptions( styleOptions.fontSize = defaultFontSize - 42; styleOptions.padding = { top: 4 }; break; + case "ko": + styleOptions.fontSize = defaultFontSize - 38; + styleOptions.padding = { top: 4, left: 6 }; + break; + case "zh-CN": + case "zh-TW": + styleOptions.fontSize = defaultFontSize - 42; + styleOptions.padding = { top: 5, left: 14 }; + break; default: styleOptions.fontSize = defaultFontSize - 30; styleOptions.padding = { left: 12 }; @@ -456,7 +452,7 @@ export function getTextStyleOptions( break; } - const shadowColor = getTextColor(style, true, uiTheme); + const shadowColor = getTextColor(style, true); if (extraStyleOptions) { if (extraStyleOptions.fontSize) { @@ -471,8 +467,8 @@ export function getTextStyleOptions( return { scale, styleOptions, shadowColor, shadowXpos, shadowYpos }; } -export function getBBCodeFrag(content: string, textStyle: TextStyle, uiTheme: UiTheme = UiTheme.DEFAULT): string { - return `[color=${getTextColor(textStyle, false, uiTheme)}][shadow=${getTextColor(textStyle, true, uiTheme)}]${content}`; +export function getBBCodeFrag(content: string, textStyle: TextStyle): string { + return `[color=${getTextColor(textStyle, false)}][shadow=${getTextColor(textStyle, true)}]${content}`; } /** @@ -491,14 +487,9 @@ export function getBBCodeFrag(content: string, textStyle: TextStyle, uiTheme: Ui * @param forWindow set to `true` if the text is to be displayed in a window ({@linkcode BattleScene.addWindow}) * it will replace all instances of the default MONEY TextStyle by {@linkcode TextStyle.MONEY_WINDOW} */ -export function getTextWithColors( - content: string, - primaryStyle: TextStyle, - uiTheme: UiTheme, - forWindow?: boolean, -): string { +export function getTextWithColors(content: string, primaryStyle: TextStyle, forWindow?: boolean): string { // Apply primary styling before anything else - let text = getBBCodeFrag(content, primaryStyle, uiTheme) + "[/color][/shadow]"; + let text = getBBCodeFrag(content, primaryStyle) + "[/color][/shadow]"; const primaryStyleString = [...text.match(new RegExp(/\[color=[^[]*\]\[shadow=[^[]*\]/i))!][0]; /* For money text displayed in game windows, we can't use the default {@linkcode TextStyle.MONEY} @@ -511,10 +502,7 @@ export function getTextWithColors( // Set custom colors text = text.replace(/@\[([^{]*)\]{([^}]*)}/gi, (_substring, textStyle: string, textToColor: string) => { return ( - "[/color][/shadow]" + - getBBCodeFrag(textToColor, TextStyle[textStyle], uiTheme) + - "[/color][/shadow]" + - primaryStyleString + "[/color][/shadow]" + getBBCodeFrag(textToColor, TextStyle[textStyle]) + "[/color][/shadow]" + primaryStyleString ); }); @@ -523,8 +511,8 @@ export function getTextWithColors( } // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: This is a giant switch which is the best option. -export function getTextColor(textStyle: TextStyle, shadow?: boolean, uiTheme: UiTheme = UiTheme.DEFAULT): string { - const isLegacyTheme = uiTheme === UiTheme.LEGACY; +export function getTextColor(textStyle: TextStyle, shadow?: boolean): string { + const isLegacyTheme = globalScene.uiTheme === UiTheme.LEGACY; switch (textStyle) { case TextStyle.MESSAGE: return !shadow ? "#f8f8f8" : "#6b5a73"; diff --git a/src/ui/title-ui-handler.ts b/src/ui/title-ui-handler.ts index 5ae195231e5..ef814167631 100644 --- a/src/ui/title-ui-handler.ts +++ b/src/ui/title-ui-handler.ts @@ -141,7 +141,8 @@ export class TitleUiHandler extends OptionSelectUiHandler { }), ); - this.appVersionText.setText("v" + version); + const betaText = import.meta.env.DEV ? " (Beta)" : ""; + this.appVersionText.setText("v" + version + betaText); const ui = this.getUi(); diff --git a/src/ui/ui-handler.ts b/src/ui/ui-handler.ts index 7dde6b22dcd..558cb08f252 100644 --- a/src/ui/ui-handler.ts +++ b/src/ui/ui-handler.ts @@ -1,8 +1,6 @@ import { globalScene } from "#app/global-scene"; import type { Button } from "#enums/buttons"; -import type { TextStyle } from "#enums/text-style"; import type { UiMode } from "#enums/ui-mode"; -import { getTextColor } from "#ui/text"; /** * A basic abstract class to act as a holder and processor for UI elements. @@ -33,10 +31,6 @@ export abstract class UiHandler { return globalScene.ui; } - getTextColor(style: TextStyle, shadow = false): string { - return getTextColor(style, shadow, globalScene.uiTheme); - } - getCursor(): number { return this.cursor; } diff --git a/src/ui/ui-theme.ts b/src/ui/ui-theme.ts index f2d434c024a..9e130417b43 100644 --- a/src/ui/ui-theme.ts +++ b/src/ui/ui-theme.ts @@ -51,7 +51,7 @@ export function addWindow( windowVariant = WindowVariant.NORMAL; } - const borderSize = globalScene.uiTheme ? 6 : 8; + const borderSize = globalScene.uiTheme === UiTheme.LEGACY ? 6 : 8; const window = globalScene.add.nineslice( x, @@ -153,7 +153,11 @@ export function addUiThemeOverrides(): void { frame?: string | number, ): Phaser.GameObjects.Image { let legacy = false; - if (typeof texture === "string" && globalScene.uiTheme && legacyCompatibleImages.includes(texture)) { + if ( + typeof texture === "string" && + globalScene.uiTheme === UiTheme.LEGACY && + legacyCompatibleImages.includes(texture) + ) { legacy = true; texture += "_legacy"; } @@ -176,7 +180,11 @@ export function addUiThemeOverrides(): void { frame?: string | number, ): Phaser.GameObjects.Sprite { let legacy = false; - if (typeof texture === "string" && globalScene.uiTheme && legacyCompatibleImages.includes(texture)) { + if ( + typeof texture === "string" && + globalScene.uiTheme === UiTheme.LEGACY && + legacyCompatibleImages.includes(texture) + ) { legacy = true; texture += "_legacy"; } @@ -205,7 +213,11 @@ export function addUiThemeOverrides(): void { bottomHeight?: number, ): Phaser.GameObjects.NineSlice { let legacy = false; - if (typeof texture === "string" && globalScene.uiTheme && legacyCompatibleImages.includes(texture)) { + if ( + typeof texture === "string" && + globalScene.uiTheme === UiTheme.LEGACY && + legacyCompatibleImages.includes(texture) + ) { legacy = true; texture += "_legacy"; } diff --git a/src/utils/common.ts b/src/utils/common.ts index aac1ef359e6..97e61b902d8 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -133,10 +133,6 @@ export function randSeedItem(items: T[]): T { return items.length === 1 ? items[0] : Phaser.Math.RND.pick(items); } -export function randSeedWeightedItem(items: T[]): T { - return items.length === 1 ? items[0] : Phaser.Math.RND.weightedPick(items); -} - /** * Shuffle a list using the seeded rng. Utilises the Fisher-Yates algorithm. * @param {Array} items An array of items. @@ -276,25 +272,11 @@ export function executeIf(condition: boolean, promiseFunc: () => Promise): } export const sessionIdKey = "pokerogue_sessionId"; -// Check if the current hostname is 'localhost' or an IP address, and ensure a port is specified -export const isLocal = - ((window.location.hostname === "localhost" || /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/.test(window.location.hostname)) && - window.location.port !== "") || - window.location.hostname === ""; -/** - * @deprecated Refer to [pokerogue-api.ts](./plugins/api/pokerogue-api.ts) instead - */ -export const localServerUrl = - import.meta.env.VITE_SERVER_URL ?? `http://${window.location.hostname}:${window.location.port + 1}`; +/** `true` when run via `pnpm start:dev` (which runs `vite --mode development`) */ +export const isLocal = import.meta.env.MODE === "development"; -/** - * Set the server URL based on whether it's local or not - * - * @deprecated Refer to [pokerogue-api.ts](./plugins/api/pokerogue-api.ts) instead - */ -export const apiUrl = localServerUrl ?? "https://api.pokerogue.net"; -// used to disable api calls when isLocal is true and a server is not found +/** Used to disable api calls when isLocal is true and a server is not found */ export let isLocalServerConnected = true; /** @@ -302,7 +284,7 @@ export let isLocalServerConnected = true; * with a GET request to verify if a server is running, * sets isLocalServerConnected based on results */ -export async function localPing() { +export async function localPing(): Promise { if (isLocal) { const titleStats = await pokerogueApi.getGameTitleStats(); isLocalServerConnected = !!titleStats; diff --git a/src/utils/data.ts b/src/utils/data.ts index 6580ecf2ee9..75047c38d25 100644 --- a/src/utils/data.ts +++ b/src/utils/data.ts @@ -8,7 +8,7 @@ import { AES, enc } from "crypto-js"; * @param values - The object to be deep copied. * @returns A new object that is a deep copy of the input. */ -export function deepCopy(values: object): object { +export function deepCopy(values: T): T { // Convert the object to a JSON string and parse it back to an object to perform a deep copy return JSON.parse(JSON.stringify(values)); } @@ -58,13 +58,28 @@ export function decrypt(data: string, bypassLogin: boolean): string { return AES.decrypt(data, saveKey).toString(enc.Utf8); } +/** + * Check if an object has no properties of its own (its shape is `{}`). An empty array is considered a bare object. + * @param obj - Object to check + * @returns - Whether the object is bare + */ +export function isBareObject(obj: any): boolean { + if (typeof obj !== "object") { + return false; + } + for (const _ in obj) { + return false; + } + return true; +} + // the latest data saved/loaded for the Starter Preferences. Required to reduce read/writes. Initialize as "{}", since this is the default value and no data needs to be stored if present. // if they ever add private static variables, move this into StarterPrefs const StarterPrefers_DEFAULT: string = "{}"; let StarterPrefers_private_latest: string = StarterPrefers_DEFAULT; export interface StarterPreferences { - [key: number]: StarterAttributes; + [key: number]: StarterAttributes | undefined; } // called on starter selection show once @@ -74,11 +89,17 @@ export function loadStarterPreferences(): StarterPreferences { localStorage.getItem(`starterPrefs_${loggedInUser?.username}`) || StarterPrefers_DEFAULT), ); } -// called on starter selection clear, always export function saveStarterPreferences(prefs: StarterPreferences): void { - const pStr: string = JSON.stringify(prefs); + // Fastest way to check if an object has any properties (does no allocation) + if (isBareObject(prefs)) { + console.warn("Refusing to save empty starter preferences"); + return; + } + // no reason to store `{}` (for starters not customized) + const pStr: string = JSON.stringify(prefs, (_, value) => (isBareObject(value) ? undefined : value)); if (pStr !== StarterPrefers_private_latest) { + console.log("%cSaving starter preferences", "color: blue"); // something changed, store the update localStorage.setItem(`starterPrefs_${loggedInUser?.username}`, pStr); // update the latest prefs diff --git a/src/utils/utility-vars.ts b/src/utils/utility-vars.ts index 081f70164c8..1f8eca00650 100644 --- a/src/utils/utility-vars.ts +++ b/src/utils/utility-vars.ts @@ -1 +1,4 @@ -export const isBeta = import.meta.env.MODE === "beta"; // this checks to see if the env mode is development. Technically this gives the same value for beta AND for dev envs +// TODO: move this (and other global constants) to `src/constants/*-constants.ts` + +/** `true` if running on `beta.pokerogue.net` or via `pnpm start:beta` (which runs `vite --mode beta`) */ +export const isBeta = import.meta.env.MODE === "beta"; diff --git a/test/@types/vitest.d.ts b/test/@types/vitest.d.ts index 2ed0512538a..f0bbdf37932 100644 --- a/test/@types/vitest.d.ts +++ b/test/@types/vitest.d.ts @@ -1,8 +1,10 @@ import "vitest"; -import type { TerrainType } from "#app/data/terrain"; +import type { Phase } from "#app/phase"; import type Overrides from "#app/overrides"; import type { ArenaTag } from "#data/arena-tag"; +import type { TerrainType } from "#data/terrain"; +import type { BattlerTag } from "#data/battler-tags"; import type { PositionalTag } from "#data/positional-tags/positional-tag"; import type { AbilityId } from "#enums/ability-id"; import type { ArenaTagSide } from "#enums/arena-tag-side"; @@ -22,10 +24,12 @@ import type { toHaveEffectiveStatOptions } from "#test/test-utils/matchers/to-ha import type { toHavePositionalTagOptions } from "#test/test-utils/matchers/to-have-positional-tag"; import type { expectedStatusType } from "#test/test-utils/matchers/to-have-status-effect"; import type { toHaveTypesOptions } from "#test/test-utils/matchers/to-have-types"; +import type { PhaseString } from "#types/phase-types"; import type { TurnMove } from "#types/turn-move"; import type { AtLeastOne } from "#types/type-helpers"; import type { toDmgValue } from "utils/common"; import type { expect } from "vitest"; +import { toHaveBattlerTagOptions } from "#test/test-utils/matchers/to-have-battler-tag"; declare module "vitest" { interface Assertion { @@ -40,6 +44,12 @@ declare module "vitest" { */ toEqualArrayUnsorted(expected: T[]): void; + /** + * Check if the currently-running {@linkcode Phase} is of the given type. + * @param expectedPhase - The expected {@linkcode PhaseString} + */ + toBeAtPhase(expectedPhase: PhaseString): void; + // #region Arena Matchers /** @@ -125,10 +135,15 @@ declare module "vitest" { toHaveStatStage(stat: BattleStat, expectedStage: number): void; /** - * Check whether a {@linkcode Pokemon} has a specific {@linkcode BattlerTagType}. - * @param expectedBattlerTagType - The expected {@linkcode BattlerTagType} + * Check whether a {@linkcode Pokemon} has the given {@linkcode BattlerTag}. + * @param expectedTag - A partially-filled {@linkcode BattlerTag} containing the desired properties */ - toHaveBattlerTag(expectedBattlerTagType: BattlerTagType): void; + toHaveBattlerTag(expectedTag: toHaveBattlerTagOptions): void; + /** + * Check whether a {@linkcode Pokemon} has the given {@linkcode BattlerTag}. + * @param expectedType - The expected {@linkcode BattlerTagType} + */ + toHaveBattlerTag(expectedType: BattlerTagType): void; /** * Check whether a {@linkcode Pokemon} has applied a specific {@linkcode AbilityId}. diff --git a/test/abilities/disguise.test.ts b/test/abilities/disguise.test.ts index f36501cb647..8a7e9a05ddb 100644 --- a/test/abilities/disguise.test.ts +++ b/test/abilities/disguise.test.ts @@ -196,7 +196,7 @@ describe("Abilities - Disguise", () => { game.move.select(MoveId.SHADOW_SNEAK); await game.toNextWave(); - expect(game.scene.phaseManager.getCurrentPhase()?.constructor.name).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); expect(game.scene.currentBattle.waveIndex).toBe(2); }); diff --git a/test/abilities/intimidate.test.ts b/test/abilities/intimidate.test.ts index 3c283e0392b..8064f1e62aa 100644 --- a/test/abilities/intimidate.test.ts +++ b/test/abilities/intimidate.test.ts @@ -35,13 +35,43 @@ describe("Abilities - Intimidate", () => { it("should lower all opponents' ATK by 1 stage on entry and switch", async () => { await game.classicMode.startBattle([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]); + const [mightyena, poochyena] = game.scene.getPlayerParty(); + const enemy = game.field.getEnemyPokemon(); expect(enemy.getStatStage(Stat.ATK)).toBe(-1); + expect(mightyena).toHaveAbilityApplied(AbilityId.INTIMIDATE); game.doSwitchPokemon(1); await game.toNextTurn(); + expect(poochyena.isActive()).toBe(true); expect(enemy.getStatStage(Stat.ATK)).toBe(-2); + expect(poochyena).toHaveAbilityApplied(AbilityId.INTIMIDATE); + }); + + it("should trigger once on initial switch prompt without cancelling opposing abilities", async () => { + await game.classicMode.runToSummon([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]); + await game.classicMode.startBattleWithSwitch(1); + + const [poochyena, mightyena] = game.scene.getPlayerParty(); + expect(poochyena.species.speciesId).toBe(SpeciesId.POOCHYENA); + + const enemy = game.field.getEnemyPokemon(); + expect(enemy).toHaveStatStage(Stat.ATK, -1); + expect(poochyena).toHaveStatStage(Stat.ATK, -1); + + expect(poochyena).toHaveAbilityApplied(AbilityId.INTIMIDATE); + expect(mightyena).not.toHaveAbilityApplied(AbilityId.INTIMIDATE); + }); + + it("should activate on reload with single party", async () => { + await game.classicMode.startBattle([SpeciesId.MIGHTYENA]); + + expect(game.field.getEnemyPokemon()).toHaveStatStage(Stat.ATK, -1); + + await game.reload.reloadSession(); + + expect(game.field.getEnemyPokemon()).toHaveStatStage(Stat.ATK, -1); }); it("should lower ATK of all opponents in a double battle", async () => { diff --git a/test/abilities/moody.test.ts b/test/abilities/moody.test.ts index d1f8aa2e351..b7882c15ced 100644 --- a/test/abilities/moody.test.ts +++ b/test/abilities/moody.test.ts @@ -84,4 +84,40 @@ describe("Abilities - Moody", () => { expect(decreasedStat).toBeTruthy(); expect(decreasedStat.length).toBe(1); }); + + it("should only try to increase a stat stage by 1 if the stat stage is not at 6", async () => { + await game.classicMode.startBattle(); + + const playerPokemon = game.field.getPlayerPokemon(); + + // Set all stat stages to 6 + vi.spyOn(playerPokemon.summonData, "statStages", "get").mockReturnValue(new Array(BATTLE_STATS.length).fill(6)); + + // Set one of the stat stages to -6 + const raisedStat = EFFECTIVE_STATS[playerPokemon.randBattleSeedInt(EFFECTIVE_STATS.length)]; + playerPokemon.setStatStage(raisedStat, -6); + + game.move.select(MoveId.SPLASH); + await game.toNextTurn(); + + expect(playerPokemon.getStatStage(raisedStat), "should increase only the stat that is not at stage 6").toBe(-4); + }); + + it("should only try to decrease a stat stage by 1 if the stat stage is not at -6", async () => { + await game.classicMode.startBattle(); + + const playerPokemon = game.field.getPlayerPokemon(); + + // Set all stat stages to -6 + vi.spyOn(playerPokemon.summonData, "statStages", "get").mockReturnValue(new Array(BATTLE_STATS.length).fill(-6)); + + // Set one of the stat stages to 6 + const raisedStat = EFFECTIVE_STATS[playerPokemon.randBattleSeedInt(EFFECTIVE_STATS.length)]; + playerPokemon.setStatStage(raisedStat, 6); + + game.move.select(MoveId.SPLASH); + await game.toNextTurn(); + + expect(playerPokemon.getStatStage(raisedStat), "should decrease only the stat that is not at stage -6").toBe(5); + }); }); diff --git a/test/abilities/pastel-veil.test.ts b/test/abilities/pastel-veil.test.ts index c4b368c94d0..cc414fa6f87 100644 --- a/test/abilities/pastel-veil.test.ts +++ b/test/abilities/pastel-veil.test.ts @@ -3,7 +3,6 @@ import { BattlerIndex } from "#enums/battler-index"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { StatusEffect } from "#enums/status-effect"; -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"; @@ -24,48 +23,35 @@ describe("Abilities - Pastel Veil", () => { beforeEach(() => { game = new GameManager(phaserGame); - game.override - .battleStyle("double") - .moveset([MoveId.TOXIC_THREAD, MoveId.SPLASH]) - .enemyAbility(AbilityId.BALL_FETCH) - .enemySpecies(SpeciesId.SUNKERN) - .enemyMoveset(MoveId.SPLASH); + game.override.battleStyle("double").enemyAbility(AbilityId.BALL_FETCH).enemySpecies(SpeciesId.TOXAPEX); }); - it("prevents the user and its allies from being afflicted by poison", async () => { + it("should prevent the user and its allies from being poisoned", async () => { await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.GALAR_PONYTA]); - const ponyta = game.scene.getPlayerField()[1]; - const magikarp = game.scene.getPlayerField()[0]; - ponyta.abilityIndex = 1; + const [magikarp, ponyta] = game.scene.getPlayerField(); + game.field.mockAbility(ponyta, AbilityId.PASTEL_VEIL); - expect(ponyta.hasAbility(AbilityId.PASTEL_VEIL)).toBe(true); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER_2); + await game.move.forceEnemyMove(MoveId.TOXIC, BattlerIndex.PLAYER); + await game.move.forceEnemyMove(MoveId.TOXIC, BattlerIndex.PLAYER_2); + await game.toEndOfTurn(); - game.move.select(MoveId.SPLASH); - game.move.select(MoveId.TOXIC_THREAD, 1, BattlerIndex.PLAYER); - - await game.phaseInterceptor.to(TurnEndPhase); - - expect(magikarp.status?.effect).toBeUndefined(); + expect(magikarp).toHaveStatusEffect(StatusEffect.NONE); + expect(ponyta).toHaveStatusEffect(StatusEffect.NONE); }); - it("it heals the poisoned status condition of allies if user is sent out into battle", async () => { + it("should cure allies' poison if user is sent out into battle", async () => { await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS, SpeciesId.GALAR_PONYTA]); - const ponyta = game.scene.getPlayerParty()[2]; - const magikarp = game.scene.getPlayerField()[0]; - ponyta.abilityIndex = 1; + const [magikarp, , ponyta] = game.scene.getPlayerParty(); + game.field.mockAbility(ponyta, AbilityId.PASTEL_VEIL); - expect(ponyta.hasAbility(AbilityId.PASTEL_VEIL)).toBe(true); + magikarp.doSetStatus(StatusEffect.POISON); - game.move.select(MoveId.SPLASH); - game.move.select(MoveId.TOXIC_THREAD, 1, BattlerIndex.PLAYER); - - await game.phaseInterceptor.to(TurnEndPhase); - expect(magikarp.status?.effect).toBe(StatusEffect.POISON); - - game.move.select(MoveId.SPLASH); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER); game.doSwitchPokemon(2); - await game.phaseInterceptor.to(TurnEndPhase); + await game.toEndOfTurn(); - expect(magikarp.status?.effect).toBeUndefined(); + expect(magikarp).toHaveStatusEffect(StatusEffect.NONE); }); }); diff --git a/test/abilities/sweet-veil.test.ts b/test/abilities/sweet-veil.test.ts index 12eeae9f9c5..d08c3eb04f8 100644 --- a/test/abilities/sweet-veil.test.ts +++ b/test/abilities/sweet-veil.test.ts @@ -2,8 +2,9 @@ import { AbilityId } from "#enums/ability-id"; import { BattlerIndex } from "#enums/battler-index"; 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 { TurnEndPhase } from "#phases/turn-end-phase"; +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"; @@ -26,62 +27,108 @@ describe("Abilities - Sweet Veil", () => { game = new GameManager(phaserGame); game.override .battleStyle("double") - .moveset([MoveId.SPLASH, MoveId.REST, MoveId.YAWN]) + .ability(AbilityId.BALL_FETCH) .enemySpecies(SpeciesId.MAGIKARP) .enemyAbility(AbilityId.BALL_FETCH) - .enemyMoveset(MoveId.POWDER); + .enemyMoveset(MoveId.SPLASH); }); - it("prevents the user and its allies from falling asleep", async () => { + function expectNoStatus() { + game.scene.getPlayerField().forEach(p => { + expect.soft(p).toHaveStatusEffect(StatusEffect.NONE); + }); + } + + it("should prevent the user and its allies from falling asleep", async () => { await game.classicMode.startBattle([SpeciesId.SWIRLIX, SpeciesId.MAGIKARP]); - game.move.select(MoveId.SPLASH); - game.move.select(MoveId.SPLASH, 1); + game.field.mockAbility(game.field.getPlayerPokemon(), AbilityId.SWEET_VEIL); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER_2); + await game.move.forceEnemyMove(MoveId.SPORE, BattlerIndex.PLAYER); + await game.move.forceEnemyMove(MoveId.SPORE, BattlerIndex.PLAYER_2); + await game.toEndOfTurn(); - await game.phaseInterceptor.to(TurnEndPhase); - - expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false); + expectNoStatus(); }); - it("causes Rest to fail when used by the user or its allies", async () => { - game.override.enemyMoveset(MoveId.SPLASH); + it("should cause Rest to fail when used by the user or its allies", async () => { await game.classicMode.startBattle([SpeciesId.SWIRLIX, SpeciesId.MAGIKARP]); - game.move.select(MoveId.SPLASH); - game.move.select(MoveId.REST, 1); + const [swirlix, magikarp] = game.scene.getPlayerField(); + game.field.mockAbility(swirlix, AbilityId.SWEET_VEIL); + swirlix.hp = 1; + magikarp.hp = 1; - await game.phaseInterceptor.to(TurnEndPhase); + game.move.use(MoveId.REST, BattlerIndex.PLAYER); + game.move.use(MoveId.REST, BattlerIndex.PLAYER_2); + await game.toEndOfTurn(); - expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false); + expectNoStatus(); + expect(swirlix).toHaveUsedMove({ move: MoveId.REST, result: MoveResult.FAIL }); + expect(magikarp).toHaveUsedMove({ move: MoveId.REST, result: MoveResult.FAIL }); }); - it("causes Yawn to fail if used on the user or its allies", async () => { - game.override.enemyMoveset(MoveId.YAWN); + it("should cause Yawn to fail if used on the user or its allies", async () => { await game.classicMode.startBattle([SpeciesId.SWIRLIX, SpeciesId.MAGIKARP]); - game.move.select(MoveId.SPLASH); - game.move.select(MoveId.SPLASH, 1); + const [shuckle, swirlix] = game.scene.getPlayerField(); + game.field.mockAbility(swirlix, AbilityId.SWEET_VEIL); - await game.phaseInterceptor.to(TurnEndPhase); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER_2); + await game.move.forceEnemyMove(MoveId.YAWN, BattlerIndex.PLAYER); + await game.move.forceEnemyMove(MoveId.YAWN, BattlerIndex.PLAYER_2); + await game.toEndOfTurn(); - expect(game.scene.getPlayerField().every(p => !!p.getTag(BattlerTagType.DROWSY))).toBe(false); + expect(shuckle).not.toHaveBattlerTag(BattlerTagType.DROWSY); + expect(swirlix).not.toHaveBattlerTag(BattlerTagType.DROWSY); + // TODO: This dooesn't work ATM + /* + const [karp1, karp2] = game.scene.getEnemyField(); + expect(karp1).toHaveUsedMove({move: MoveId.YAWN, result: MoveResult.FAIL}); + expect(karp2).toHaveUsedMove({move: MoveId.YAWN, result: MoveResult.FAIL}); + */ }); - it("prevents the user and its allies already drowsy due to Yawn from falling asleep.", async () => { - game.override.enemySpecies(SpeciesId.PIKACHU).enemyLevel(5).startingLevel(5).enemyMoveset(MoveId.SPLASH); + it("should NOT cure allies' sleep status if user is sent out into battle", async () => { + await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.FEEBAS, SpeciesId.SWIRLIX]); - await game.classicMode.startBattle([SpeciesId.SHUCKLE, SpeciesId.SHUCKLE, SpeciesId.SWIRLIX]); + const [magikarp, , swirlix] = game.scene.getPlayerParty(); + game.field.mockAbility(swirlix, AbilityId.PASTEL_VEIL); - game.move.select(MoveId.SPLASH); - game.move.select(MoveId.YAWN, 1, BattlerIndex.PLAYER); + game.move.use(MoveId.SPLASH); + game.move.use(MoveId.SPORE, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER); + await game.toNextTurn(); - await game.phaseInterceptor.to("BerryPhase"); + expect(magikarp).toHaveStatusEffect(StatusEffect.SLEEP); - expect(game.scene.getPlayerField().some(p => !!p.getTag(BattlerTagType.DROWSY))).toBe(true); - - game.move.select(MoveId.SPLASH); + game.move.use(MoveId.SPLASH); game.doSwitchPokemon(2); + await game.toEndOfTurn(); - expect(game.scene.getPlayerField().every(p => p.status?.effect)).toBe(false); + expect(magikarp).toHaveStatusEffect(StatusEffect.SLEEP); + }); + + it("should prevent an already-drowsy user or ally from falling asleep", async () => { + await game.classicMode.startBattle([SpeciesId.SHUCKLE, SpeciesId.SWIRLIX]); + + // Add yawn before granting ability + const [shuckle, swirlix] = game.scene.getPlayerField(); + shuckle.addTag(BattlerTagType.DROWSY, 1); + swirlix.addTag(BattlerTagType.DROWSY, 1); + + game.field.mockAbility(shuckle, AbilityId.SWEET_VEIL); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER_2); + await game.toNextTurn(); + + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER_2); + await game.toNextTurn(); + + expect(shuckle).not.toHaveBattlerTag(BattlerTagType.DROWSY); + expect(swirlix).not.toHaveBattlerTag(BattlerTagType.DROWSY); + expectNoStatus(); }); }); diff --git a/test/battle/special-battle.test.ts b/test/battle/special-battle.test.ts index d22931bfea5..4fb859a2a40 100644 --- a/test/battle/special-battle.test.ts +++ b/test/battle/special-battle.test.ts @@ -36,62 +36,62 @@ describe("Test Battle Phase", () => { game.override.battleStyle("single").startingWave(10); await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]); expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); }); it("startBattle 2vs2 boss", async () => { game.override.battleStyle("double").startingWave(10); await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]); expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); }); it("startBattle 2vs2 trainer", async () => { game.override.battleStyle("double").startingWave(5); await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]); expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); }); it("startBattle 2vs1 trainer", async () => { game.override.battleStyle("single").startingWave(5); await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]); expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); }); it("startBattle 2vs1 rival", async () => { game.override.battleStyle("single").startingWave(8); await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]); expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); }); it("startBattle 2vs2 rival", async () => { game.override.battleStyle("double").startingWave(8); await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]); expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); }); it("startBattle 1vs1 trainer", async () => { game.override.battleStyle("single").startingWave(5); await game.classicMode.startBattle([SpeciesId.BLASTOISE]); expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); }); it("startBattle 2vs2 trainer", async () => { game.override.battleStyle("double").startingWave(5); await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD]); expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); }); it("startBattle 4vs2 trainer", async () => { game.override.battleStyle("double").startingWave(5); await game.classicMode.startBattle([SpeciesId.BLASTOISE, SpeciesId.CHARIZARD, SpeciesId.DARKRAI, SpeciesId.GABITE]); expect(game.scene.ui?.getMode()).toBe(UiMode.COMMAND); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); }); }); diff --git a/test/evolution.test.ts b/test/evolution.test.ts index 3fb763e9190..7079404bdec 100644 --- a/test/evolution.test.ts +++ b/test/evolution.test.ts @@ -175,4 +175,27 @@ describe("Evolution", () => { expect(fourForm.evoFormKey).toBe("four"); // meanwhile, according to the pokemon-forms, the evoFormKey for a 4 family maushold is "four" } }); + + it("tyrogue should evolve if move is not in first slot", async () => { + game.override + .moveset([MoveId.TACKLE, MoveId.RAPID_SPIN, MoveId.LOW_KICK]) + .enemySpecies(SpeciesId.GOLEM) + .enemyMoveset(MoveId.SPLASH) + .startingWave(41) + .startingLevel(19) + .enemyLevel(30); + + await game.classicMode.startBattle([SpeciesId.TYROGUE]); + + const tyrogue = game.field.getPlayerPokemon(); + + const golem = game.field.getEnemyPokemon(); + golem.hp = 1; + expect(golem.hp).toBe(1); + + game.move.select(MoveId.TACKLE); + await game.phaseInterceptor.to("EndEvolutionPhase"); + + expect(tyrogue.species.speciesId).toBe(SpeciesId.HITMONTOP); + }); }); diff --git a/test/items/leftovers.test.ts b/test/items/leftovers.test.ts index 6ae4094799b..484843b81ff 100644 --- a/test/items/leftovers.test.ts +++ b/test/items/leftovers.test.ts @@ -2,7 +2,6 @@ import { AbilityId } from "#enums/ability-id"; import { MoveId } from "#enums/move-id"; import { SpeciesId } from "#enums/species-id"; import { DamageAnimPhase } from "#phases/damage-anim-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"; @@ -54,7 +53,7 @@ describe("Items - Leftovers", () => { const leadHpAfterDamage = leadPokemon.hp; // Check if leftovers heal us - await game.phaseInterceptor.to(TurnEndPhase); + await game.phaseInterceptor.to("PokemonHealPhase"); expect(leadPokemon.hp).toBeGreaterThan(leadHpAfterDamage); }); }); diff --git a/test/matchers.setup.ts b/test/matchers.setup.ts index f76a9423ab3..fe2135f4db4 100644 --- a/test/matchers.setup.ts +++ b/test/matchers.setup.ts @@ -1,3 +1,4 @@ +import { toBeAtPhase } from "#test/test-utils/matchers/to-be-at-phase"; import { toEqualArrayUnsorted } from "#test/test-utils/matchers/to-equal-array-unsorted"; import { toHaveAbilityApplied } from "#test/test-utils/matchers/to-have-ability-applied"; import { toHaveArenaTag } from "#test/test-utils/matchers/to-have-arena-tag"; @@ -24,6 +25,7 @@ import { expect } from "vitest"; expect.extend({ toEqualArrayUnsorted, + toBeAtPhase, toHaveWeather, toHaveTerrain, toHaveArenaTag, diff --git a/test/moves/dragon-cheer.test.ts b/test/moves/dragon-cheer.test.ts index 614dd9ab6ab..50880e067d9 100644 --- a/test/moves/dragon-cheer.test.ts +++ b/test/moves/dragon-cheer.test.ts @@ -1,15 +1,18 @@ import { AbilityId } from "#enums/ability-id"; import { BattlerIndex } from "#enums/battler-index"; +import { BattlerTagType } from "#enums/battler-tag-type"; 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 { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; -describe("Moves - Dragon Cheer", () => { +describe("Move - Dragon Cheer", () => { let phaserGame: Phaser.Game; let game: GameManager; + beforeAll(() => { phaserGame = new Phaser.Game({ type: Phaser.HEADLESS, @@ -24,75 +27,81 @@ describe("Moves - Dragon Cheer", () => { game = new GameManager(phaserGame); game.override .battleStyle("double") + .ability(AbilityId.BALL_FETCH) .enemyAbility(AbilityId.BALL_FETCH) .enemyMoveset(MoveId.SPLASH) - .enemyLevel(20) - .moveset([MoveId.DRAGON_CHEER, MoveId.TACKLE, MoveId.SPLASH]); + .enemyLevel(20); }); - it("increases the user's allies' critical hit ratio by one stage", async () => { + it("should increase non-Dragon type allies' crit ratios by 1 stage", async () => { await game.classicMode.startBattle([SpeciesId.DRAGONAIR, SpeciesId.MAGIKARP]); - const enemy = game.scene.getEnemyField()[0]; - + const enemy = game.field.getEnemyPokemon(); vi.spyOn(enemy, "getCritStage"); - game.move.select(MoveId.DRAGON_CHEER, 0); - game.move.select(MoveId.TACKLE, 1, BattlerIndex.ENEMY); - + game.move.use(MoveId.DRAGON_CHEER, BattlerIndex.PLAYER); + game.move.use(MoveId.TACKLE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.toEndOfTurn(); - // After Tackle - await game.phaseInterceptor.to("TurnEndPhase"); + const [dragonair, magikarp] = game.scene.getPlayerField(); + expect(dragonair).not.toHaveBattlerTag(BattlerTagType.DRAGON_CHEER); + expect(magikarp).toHaveBattlerTag({ tagType: BattlerTagType.DRAGON_CHEER, critStages: 1 }); expect(enemy.getCritStage).toHaveReturnedWith(1); // getCritStage is called on defender }); - it("increases the user's Dragon-type allies' critical hit ratio by two stages", async () => { + it("should increase Dragon-type allies' crit ratios by 2 stages", async () => { await game.classicMode.startBattle([SpeciesId.MAGIKARP, SpeciesId.DRAGONAIR]); - const enemy = game.scene.getEnemyField()[0]; - + const enemy = game.field.getEnemyPokemon(); vi.spyOn(enemy, "getCritStage"); - game.move.select(MoveId.DRAGON_CHEER, 0); - game.move.select(MoveId.TACKLE, 1, BattlerIndex.ENEMY); - + game.move.use(MoveId.DRAGON_CHEER, BattlerIndex.PLAYER); + game.move.use(MoveId.TACKLE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); + await game.toEndOfTurn(); - // After Tackle - await game.phaseInterceptor.to("TurnEndPhase"); + const [magikarp, dragonair] = game.scene.getPlayerField(); + expect(magikarp).not.toHaveBattlerTag(BattlerTagType.DRAGON_CHEER); + expect(dragonair).toHaveBattlerTag({ tagType: BattlerTagType.DRAGON_CHEER, critStages: 2 }); expect(enemy.getCritStage).toHaveReturnedWith(2); // getCritStage is called on defender }); - it("applies the effect based on the allies' type upon use of the move, and do not change if the allies' type changes later in battle", async () => { + it("should maintain crit boost amount even if user's type is changed", async () => { await game.classicMode.startBattle([SpeciesId.DRAGONAIR, SpeciesId.MAGIKARP]); - const magikarp = game.scene.getPlayerField()[1]; - const enemy = game.scene.getEnemyField()[0]; - - vi.spyOn(enemy, "getCritStage"); - - game.move.select(MoveId.DRAGON_CHEER, 0); - game.move.select(MoveId.TACKLE, 1, BattlerIndex.ENEMY); - + // Use Reflect Type to become Dragon-type mid-turn + game.move.use(MoveId.DRAGON_CHEER, BattlerIndex.PLAYER); + game.move.use(MoveId.REFLECT_TYPE, BattlerIndex.PLAYER_2, BattlerIndex.PLAYER); await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); - - // After Tackle - await game.phaseInterceptor.to("TurnEndPhase"); - expect(enemy.getCritStage).toHaveReturnedWith(1); // getCritStage is called on defender - - await game.toNextTurn(); - - // Change Magikarp's type to Dragon - vi.spyOn(magikarp, "getTypes").mockReturnValue([PokemonType.DRAGON]); - expect(magikarp.getTypes()).toEqual([PokemonType.DRAGON]); - - game.move.select(MoveId.SPLASH, 0); - game.move.select(MoveId.TACKLE, 1, BattlerIndex.ENEMY); - - await game.setTurnOrder([BattlerIndex.PLAYER_2, BattlerIndex.PLAYER, BattlerIndex.ENEMY, BattlerIndex.ENEMY_2]); - await game.phaseInterceptor.to("MoveEndPhase"); - expect(enemy.getCritStage).toHaveReturnedWith(1); // getCritStage is called on defender + + // Dragon cheer added +1 stages + const magikarp = game.scene.getPlayerField()[1]; + expect(magikarp).toHaveBattlerTag({ tagType: BattlerTagType.DRAGON_CHEER, critStages: 1 }); + expect(magikarp).toHaveTypes([PokemonType.WATER]); + + await game.toEndOfTurn(); + + // Should be dragon type, but still with a +1 stage boost + expect(magikarp).toHaveTypes([PokemonType.DRAGON]); + expect(magikarp).toHaveBattlerTag({ tagType: BattlerTagType.DRAGON_CHEER, critStages: 1 }); + }); + + it.each([ + { name: "Focus Energy", tagType: BattlerTagType.CRIT_BOOST }, + { name: "Dragon Cheer", tagType: BattlerTagType.DRAGON_CHEER }, + ])("should fail if $name is already present", async ({ tagType }) => { + await game.classicMode.startBattle([SpeciesId.DRAGONAIR, SpeciesId.MAGIKARP]); + + const [dragonair, magikarp] = game.scene.getPlayerField(); + magikarp.addTag(tagType); + + game.move.use(MoveId.DRAGON_CHEER, BattlerIndex.PLAYER); + game.move.use(MoveId.SPLASH, BattlerIndex.PLAYER_2); + await game.toEndOfTurn(); + + expect(dragonair).toHaveUsedMove({ move: MoveId.DRAGON_CHEER, result: MoveResult.FAIL }); + expect(magikarp).toHaveBattlerTag(tagType); }); }); diff --git a/test/moves/entry-hazards.test.ts b/test/moves/entry-hazards.test.ts index 6739b5980a4..30f773bc9af 100644 --- a/test/moves/entry-hazards.test.ts +++ b/test/moves/entry-hazards.test.ts @@ -200,7 +200,7 @@ describe("Moves - Entry Hazards", () => { expect(enemy).toHaveTakenDamage(enemy.getMaxHp() * 0.125 * multi); expect(game.textInterceptor.logs).toContain( i18next.t("arenaTag:stealthRockActivateTrap", { - pokemonName: getPokemonNameWithAffix(enemy), + pokemonNameWithAffix: getPokemonNameWithAffix(enemy), }), ); }); diff --git a/test/moves/focus-energy.test.ts b/test/moves/focus-energy.test.ts new file mode 100644 index 00000000000..3c2882f5bf3 --- /dev/null +++ b/test/moves/focus-energy.test.ts @@ -0,0 +1,69 @@ +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 { GameManager } from "#test/test-utils/game-manager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +describe("Move - Focus Energy", () => { + 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) + .startingLevel(100) + .enemyLevel(100); + }); + + it("should increase the user's crit ratio by 2 stages", async () => { + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + + game.move.use(MoveId.FOCUS_ENERGY); + await game.toNextTurn(); + + const feebas = game.field.getPlayerPokemon(); + expect(feebas).toHaveBattlerTag({ tagType: BattlerTagType.CRIT_BOOST, critStages: 2 }); + + const enemy = game.field.getEnemyPokemon(); + vi.spyOn(enemy, "getCritStage"); + + game.move.use(MoveId.TACKLE); + await game.toEndOfTurn(); + + expect(enemy.getCritStage).toHaveReturnedWith(2); + }); + + it.each([ + { name: "Focus Energy", tagType: BattlerTagType.CRIT_BOOST }, + { name: "Dragon Cheer", tagType: BattlerTagType.DRAGON_CHEER }, + ])("should fail if $name is already present", async ({ tagType }) => { + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + + const feebas = game.field.getPlayerPokemon(); + feebas.addTag(tagType); + + game.move.use(MoveId.FOCUS_ENERGY); + await game.toEndOfTurn(); + + expect(feebas).toHaveUsedMove({ move: MoveId.FOCUS_ENERGY, result: MoveResult.FAIL }); + }); +}); diff --git a/test/moves/pollen-puff.test.ts b/test/moves/pollen-puff.test.ts index 76732a39c43..02772055f1f 100644 --- a/test/moves/pollen-puff.test.ts +++ b/test/moves/pollen-puff.test.ts @@ -61,4 +61,16 @@ describe("Moves - Pollen Puff", () => { expect(target.battleData.hitCount).toBe(2); }); + + // Regression test for pollen puff healing an enemy after dealing damage + it("should not heal an enemy after dealing damage", async () => { + await game.classicMode.startBattle([SpeciesId.FEEBAS]); + const target = game.field.getEnemyPokemon(); + game.move.use(MoveId.POLLEN_PUFF); + + await game.phaseInterceptor.to("BerryPhase", false); + + expect(target.hp).not.toBe(target.getMaxHp()); + expect(game.phaseInterceptor.log).not.toContain("PokemonHealPhase"); + }); }); diff --git a/test/moves/transform-imposter.test.ts b/test/moves/transform-imposter.test.ts index b1631130154..1b38a4bce9c 100644 --- a/test/moves/transform-imposter.test.ts +++ b/test/moves/transform-imposter.test.ts @@ -212,7 +212,7 @@ describe("Transforming Effects", () => { await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.toNextWave(); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); expect(game.scene.currentBattle.waveIndex).toBe(2); await game.reload.reloadSession(); @@ -242,7 +242,7 @@ describe("Transforming Effects", () => { await game.setTurnOrder([BattlerIndex.PLAYER, BattlerIndex.ENEMY]); await game.toNextWave(); - expect(game.scene.phaseManager.getCurrentPhase()?.phaseName).toBe("CommandPhase"); + expect(game).toBeAtPhase("CommandPhase"); expect(game.scene.currentBattle.waveIndex).toBe(2); expect(player.getSpeciesForm().speciesId).toBe(enemy.getSpeciesForm().speciesId); diff --git a/test/mystery-encounter/encounters/a-trainers-test-encounter.test.ts b/test/mystery-encounter/encounters/a-trainers-test-encounter.test.ts index 93cf4537c53..b4bd74d44d6 100644 --- a/test/mystery-encounter/encounters/a-trainers-test-encounter.test.ts +++ b/test/mystery-encounter/encounters/a-trainers-test-encounter.test.ts @@ -9,7 +9,6 @@ import { ATrainersTestEncounter } from "#mystery-encounters/a-trainers-test-enco import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { HUMAN_TRANSITABLE_BIOMES } from "#mystery-encounters/mystery-encounters"; -import { CommandPhase } from "#phases/command-phase"; import { PartyHealPhase } from "#phases/party-heal-phase"; import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { @@ -106,7 +105,7 @@ describe("A Trainer's Test - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(scene.currentBattle.trainer).toBeDefined(); expect( @@ -131,7 +130,7 @@ describe("A Trainer's Test - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to(SelectModifierPhase, false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); const eggsAfter = scene.gameData.eggs; expect(eggsAfter).toBeDefined(); @@ -179,7 +178,7 @@ describe("A Trainer's Test - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2); await game.phaseInterceptor.to(SelectModifierPhase, false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); const eggsAfter = scene.gameData.eggs; expect(eggsAfter).toBeDefined(); diff --git a/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts b/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts index 562482dd520..d269e40db0f 100644 --- a/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts +++ b/test/mystery-encounter/encounters/absolute-avarice-encounter.test.ts @@ -10,7 +10,6 @@ import { BerryModifier, PokemonHeldItemModifier } from "#modifiers/modifier"; import { AbsoluteAvariceEncounter } from "#mystery-encounters/absolute-avarice-encounter"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; -import { CommandPhase } from "#phases/command-phase"; import { MovePhase } from "#phases/move-phase"; import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { @@ -132,7 +131,7 @@ describe("Absolute Avarice - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(SpeciesId.GREEDENT); const moveset = enemyField[0].moveset.map(m => m.moveId); @@ -148,7 +147,7 @@ describe("Absolute Avarice - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to(SelectModifierPhase, false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); for (const partyPokemon of scene.getPlayerParty()) { const pokemonId = partyPokemon.id; diff --git a/test/mystery-encounter/encounters/berries-abound-encounter.test.ts b/test/mystery-encounter/encounters/berries-abound-encounter.test.ts index 12c5a6515bc..5e9dffa1332 100644 --- a/test/mystery-encounter/encounters/berries-abound-encounter.test.ts +++ b/test/mystery-encounter/encounters/berries-abound-encounter.test.ts @@ -11,8 +11,6 @@ import { BerriesAboundEncounter } from "#mystery-encounters/berries-abound-encou import * as EncounterDialogueUtils from "#mystery-encounters/encounter-dialogue-utils"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; -import { CommandPhase } from "#phases/command-phase"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase, @@ -114,7 +112,7 @@ describe("Berries Abound - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); }); @@ -135,7 +133,7 @@ describe("Berries Abound - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); const berriesAfter = scene.findModifiers(m => m instanceof BerryModifier) as BerryModifier[]; const berriesAfterCount = berriesAfter.reduce((a, b) => a + b.stackCount, 0); @@ -186,7 +184,7 @@ describe("Berries Abound - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); @@ -210,7 +208,7 @@ describe("Berries Abound - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); @@ -230,8 +228,6 @@ describe("Berries Abound - Mystery Encounter", () => { }); await runMysteryEncounterToEnd(game, 2); - await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); 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 13d3c030c63..723516174fb 100644 --- a/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts +++ b/test/mystery-encounter/encounters/bug-type-superfan-encounter.test.ts @@ -12,9 +12,7 @@ import { PokemonMove } from "#moves/pokemon-move"; import { BugTypeSuperfanEncounter } from "#mystery-encounters/bug-type-superfan-encounter"; import * as encounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; -import { CommandPhase } from "#phases/command-phase"; -import { MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#phases/mystery-encounter-phases"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; +import { MysteryEncounterPhase } from "#phases/mystery-encounter-phases"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, @@ -231,7 +229,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyParty = scene.getEnemyParty(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyParty.length).toBe(2); expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN); expect(enemyParty[0].species.speciesId).toBe(SpeciesId.BEEDRILL); @@ -244,7 +242,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyParty = scene.getEnemyParty(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyParty.length).toBe(3); expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN); expect(enemyParty[0].species.speciesId).toBe(SpeciesId.BEEDRILL); @@ -258,7 +256,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyParty = scene.getEnemyParty(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyParty.length).toBe(4); expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN); expect(enemyParty[0].species.speciesId).toBe(SpeciesId.BEEDRILL); @@ -273,7 +271,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyParty = scene.getEnemyParty(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyParty.length).toBe(5); expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN); expect(enemyParty[0].species.speciesId).toBe(SpeciesId.BEEDRILL); @@ -289,7 +287,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyParty = scene.getEnemyParty(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyParty.length).toBe(5); expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN); expect(enemyParty[0].species.speciesId).toBe(SpeciesId.BEEDRILL); @@ -307,7 +305,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyParty = scene.getEnemyParty(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyParty.length).toBe(5); expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN); expect(enemyParty[0].species.speciesId).toBe(SpeciesId.BEEDRILL); @@ -325,7 +323,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyParty = scene.getEnemyParty(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyParty.length).toBe(5); expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN); expect(enemyParty[0].species.speciesId).toBe(SpeciesId.BEEDRILL); @@ -343,7 +341,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyParty = scene.getEnemyParty(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyParty.length).toBe(5); expect(scene.currentBattle.trainer?.config.trainerType).toBe(TrainerType.BUG_TYPE_SUPERFAN); expect(enemyParty[0].species.speciesId).toBe(SpeciesId.BEEDRILL); @@ -365,7 +363,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game, false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterRewardsPhase.name); + expect(game).toBeAtPhase("MysteryEncounterRewardsPhase"); game.phaseInterceptor["prompts"] = []; // Clear out prompt handlers game.onNextPrompt("MysteryEncounterRewardsPhase", UiMode.OPTION_SELECT, () => { game.endPhase(); @@ -406,7 +404,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); @@ -416,7 +414,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.BUG_TYPE_SUPERFAN, defaultParty); await runMysteryEncounterToEnd(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -435,7 +433,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { ]); await runMysteryEncounterToEnd(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -457,7 +455,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { ]); await runMysteryEncounterToEnd(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -481,7 +479,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { ]); await runMysteryEncounterToEnd(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -542,7 +540,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 3); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); @@ -557,7 +555,7 @@ describe("Bug-Type Superfan - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); diff --git a/test/mystery-encounter/encounters/clowning-around-encounter.test.ts b/test/mystery-encounter/encounters/clowning-around-encounter.test.ts index f02a5c623af..e7ec6e43392 100644 --- a/test/mystery-encounter/encounters/clowning-around-encounter.test.ts +++ b/test/mystery-encounter/encounters/clowning-around-encounter.test.ts @@ -22,10 +22,7 @@ import { ClowningAroundEncounter } from "#mystery-encounters/clowning-around-enc 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"; -import { CommandPhase } from "#phases/command-phase"; import { MovePhase } from "#phases/move-phase"; -import { PostMysteryEncounterPhase } from "#phases/mystery-encounter-phases"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase, @@ -171,7 +168,7 @@ describe("Clowning Around - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(2); expect(enemyField[0].species.speciesId).toBe(SpeciesId.MR_MIME); expect(enemyField[0].moveset).toEqual([ @@ -199,9 +196,6 @@ 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); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); - await game.phaseInterceptor.to("SelectModifierPhase"); const abilityToTrain = scene.currentBattle.mysteryEncounter?.misc.ability; game.onNextPrompt("PostMysteryEncounterPhase", UiMode.MESSAGE, () => { @@ -215,7 +209,7 @@ describe("Clowning Around - Mystery Encounter", () => { vi.spyOn(partyUiHandler, "show"); game.endPhase(); await game.phaseInterceptor.to("PostMysteryEncounterPhase"); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(PostMysteryEncounterPhase.name); + expect(game).toBeAtPhase("PostMysteryEncounterPhase"); // Wait for Yes/No confirmation to appear await vi.waitFor(() => expect(optionSelectUiHandler.show).toHaveBeenCalled()); diff --git a/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts b/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts index de47b074089..81a2fc7463c 100644 --- a/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts +++ b/test/mystery-encounter/encounters/dancing-lessons-encounter.test.ts @@ -9,11 +9,9 @@ import { UiMode } from "#enums/ui-mode"; 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"; -import { CommandPhase } from "#phases/command-phase"; import { LearnMovePhase } from "#phases/learn-move-phase"; import { MovePhase } from "#phases/move-phase"; import { MysteryEncounterPhase } from "#phases/mystery-encounter-phases"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, @@ -105,7 +103,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(SpeciesId.ORICORIO); expect(enemyField[0].summonData.statStages).toEqual([1, 1, 1, 1, 0, 0, 0]); @@ -126,7 +124,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -226,7 +224,7 @@ describe("Dancing Lessons - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 3); const partyCountAfter = scene.getPlayerParty().length; - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); diff --git a/test/mystery-encounter/encounters/delibirdy-encounter.test.ts b/test/mystery-encounter/encounters/delibirdy-encounter.test.ts index 7398b639f1c..fe17f091d0e 100644 --- a/test/mystery-encounter/encounters/delibirdy-encounter.test.ts +++ b/test/mystery-encounter/encounters/delibirdy-encounter.test.ts @@ -161,7 +161,7 @@ describe("Delibird-y - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 1); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); @@ -316,7 +316,7 @@ describe("Delibird-y - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); @@ -449,7 +449,7 @@ describe("Delibird-y - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 3); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); 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 3c19d458049..812d6d661ef 100644 --- a/test/mystery-encounter/encounters/department-store-sale-encounter.test.ts +++ b/test/mystery-encounter/encounters/department-store-sale-encounter.test.ts @@ -9,7 +9,6 @@ import { DepartmentStoreSaleEncounter } from "#mystery-encounters/department-sto 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"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounter-test-utils"; import { GameManager } from "#test/test-utils/game-manager"; import { ModifierSelectUiHandler } from "#ui/modifier-select-ui-handler"; @@ -93,7 +92,7 @@ describe("Department Store Sale - Mystery Encounter", () => { it("should have shop with only TMs", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty); await runMysteryEncounterToEnd(game, 1); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -130,7 +129,7 @@ describe("Department Store Sale - Mystery Encounter", () => { it("should have shop with only Vitamins", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty); await runMysteryEncounterToEnd(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -170,7 +169,7 @@ describe("Department Store Sale - Mystery Encounter", () => { it("should have shop with only X Items", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty); await runMysteryEncounterToEnd(game, 3); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -210,7 +209,7 @@ describe("Department Store Sale - Mystery Encounter", () => { it("should have shop with only Pokeballs", async () => { await game.runToMysteryEncounter(MysteryEncounterType.DEPARTMENT_STORE_SALE, defaultParty); await runMysteryEncounterToEnd(game, 4); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); diff --git a/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts b/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts index 54f790ca207..91a32c025d5 100644 --- a/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts +++ b/test/mystery-encounter/encounters/fiery-fallout-encounter.test.ts @@ -16,7 +16,6 @@ import { AttackTypeBoosterModifier, PokemonHeldItemModifier } from "#modifiers/m import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import { FieryFalloutEncounter } from "#mystery-encounters/fiery-fallout-encounter"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; -import { CommandPhase } from "#phases/command-phase"; import { MovePhase } from "#phases/move-phase"; import { MysteryEncounterPhase } from "#phases/mystery-encounter-phases"; import { SelectModifierPhase } from "#phases/select-modifier-phase"; @@ -161,7 +160,7 @@ describe("Fiery Fallout - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(2); expect(enemyField[0].species.speciesId).toBe(SpeciesId.VOLCARONA); expect(enemyField[1].species.speciesId).toBe(SpeciesId.VOLCARONA); @@ -177,7 +176,7 @@ describe("Fiery Fallout - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to(SelectModifierPhase, false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); const leadPokemonId = scene.getPlayerParty()?.[0].id; const leadPokemonItems = scene.findModifiers( @@ -266,7 +265,7 @@ describe("Fiery Fallout - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.FIERY_FALLOUT, defaultParty); await runMysteryEncounterToEnd(game, 3); await game.phaseInterceptor.to(SelectModifierPhase, false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); const leadPokemonItems = scene.getPlayerParty()[0].getHeldItems() as PokemonHeldItemModifier[]; const item = leadPokemonItems.find(i => i instanceof AttackTypeBoosterModifier); @@ -292,7 +291,7 @@ describe("Fiery Fallout - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 3); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(continueEncounterSpy).not.toHaveBeenCalled(); }); }); 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 8650b42ce4d..81dbad16e01 100644 --- a/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts +++ b/test/mystery-encounter/encounters/fight-or-flight-encounter.test.ts @@ -9,9 +9,7 @@ import { UiMode } from "#enums/ui-mode"; 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"; -import { CommandPhase } from "#phases/command-phase"; import { MysteryEncounterPhase } from "#phases/mystery-encounter-phases"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, @@ -109,7 +107,7 @@ describe("Fight or Flight - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); }); @@ -122,8 +120,9 @@ describe("Fight or Flight - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); + expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); const modifierSelectHandler = scene.ui.handlers.find( @@ -165,7 +164,7 @@ describe("Fight or Flight - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); @@ -182,7 +181,7 @@ describe("Fight or Flight - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); 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 7bfaaac1141..bc1a2893627 100644 --- a/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts +++ b/test/mystery-encounter/encounters/fun-and-games-encounter.test.ts @@ -14,9 +14,8 @@ import { FunAndGamesEncounter } from "#mystery-encounters/fun-and-games-encounte import { MysteryEncounter } from "#mystery-encounters/mystery-encounter"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { HUMAN_TRANSITABLE_BIOMES } from "#mystery-encounters/mystery-encounters"; -import { CommandPhase } from "#phases/command-phase"; +import type { CommandPhase } from "#phases/command-phase"; import { MysteryEncounterPhase } from "#phases/mystery-encounter-phases"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, @@ -131,7 +130,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 1); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); @@ -143,7 +142,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.FUN_AND_GAMES, defaultParty); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1 }, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(game.field.getEnemyPokemon().species.speciesId).toBe(SpeciesId.WOBBUFFET); expect(game.field.getEnemyPokemon().ivs).toEqual([0, 0, 0, 0, 0, 0]); expect(game.field.getEnemyPokemon().nature).toBe(Nature.MILD); @@ -165,7 +164,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await game.phaseInterceptor.to("SelectModifierPhase", false); // Rewards - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); }); it("should have no items in rewards if Wubboffet doesn't take enough damage", async () => { @@ -173,7 +172,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.FUN_AND_GAMES, defaultParty); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1 }, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); game.onNextPrompt("MessagePhase", UiMode.MESSAGE, () => { game.endPhase(); }); @@ -184,7 +183,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await game.phaseInterceptor.to("SelectModifierPhase", false); // Rewards - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -200,7 +199,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.FUN_AND_GAMES, defaultParty); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1 }, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); game.onNextPrompt("MessagePhase", UiMode.MESSAGE, () => { game.endPhase(); }); @@ -213,7 +212,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await game.phaseInterceptor.to("SelectModifierPhase", false); // Rewards - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -230,7 +229,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.FUN_AND_GAMES, defaultParty); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1 }, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); game.onNextPrompt("MessagePhase", UiMode.MESSAGE, () => { game.endPhase(); }); @@ -243,7 +242,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await game.phaseInterceptor.to("SelectModifierPhase", false); // Rewards - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -260,7 +259,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.FUN_AND_GAMES, defaultParty); await runMysteryEncounterToEnd(game, 1, { pokemonNo: 1 }, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); game.onNextPrompt("MessagePhase", UiMode.MESSAGE, () => { game.endPhase(); }); @@ -273,7 +272,7 @@ describe("Fun And Games! - Mystery Encounter", () => { await game.phaseInterceptor.to("SelectModifierPhase", false); // Rewards - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); 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 bb56505ac48..c8e934168bc 100644 --- a/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts +++ b/test/mystery-encounter/encounters/global-trade-system-encounter.test.ts @@ -13,7 +13,6 @@ import { generateModifierType } from "#mystery-encounters/encounter-phase-utils" import { GlobalTradeSystemEncounter } from "#mystery-encounters/global-trade-system-encounter"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { CIVILIZATION_ENCOUNTER_BIOMES } from "#mystery-encounters/mystery-encounters"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounter-test-utils"; import { GameManager } from "#test/test-utils/game-manager"; import { ModifierSelectUiHandler } from "#ui/modifier-select-ui-handler"; @@ -226,7 +225,7 @@ describe("Global Trade System - Mystery Encounter", () => { await scene.updateModifiers(true); await runMysteryEncounterToEnd(game, 3, { pokemonNo: 1, optionNo: 1 }); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); 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 73134381553..ed0ca02720c 100644 --- a/test/mystery-encounter/encounters/lost-at-sea-encounter.test.ts +++ b/test/mystery-encounter/encounters/lost-at-sea-encounter.test.ts @@ -147,7 +147,7 @@ describe("Lost at Sea - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 1); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); @@ -212,7 +212,7 @@ describe("Lost at Sea - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); diff --git a/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts b/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts index 0c4e3044bbd..b937fdcfcf5 100644 --- a/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts +++ b/test/mystery-encounter/encounters/mysterious-challengers-encounter.test.ts @@ -12,8 +12,6 @@ import { MysteriousChallengersEncounter } from "#mystery-encounters/mysterious-c import { MysteryEncounter } from "#mystery-encounters/mystery-encounter"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { HUMAN_TRANSITABLE_BIOMES } from "#mystery-encounters/mystery-encounters"; -import { CommandPhase } from "#phases/command-phase"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase, @@ -152,7 +150,7 @@ describe("Mysterious Challengers - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty); await runMysteryEncounterToEnd(game, 1, undefined, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(scene.currentBattle.trainer).toBeDefined(); expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE); }); @@ -162,7 +160,7 @@ describe("Mysterious Challengers - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -196,7 +194,7 @@ describe("Mysterious Challengers - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty); await runMysteryEncounterToEnd(game, 2, undefined, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(scene.currentBattle.trainer).toBeDefined(); expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE); }); @@ -206,7 +204,7 @@ describe("Mysterious Challengers - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -253,7 +251,7 @@ describe("Mysterious Challengers - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS, defaultParty); await runMysteryEncounterToEnd(game, 3, undefined, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(scene.currentBattle.trainer).toBeDefined(); expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE); }); @@ -262,8 +260,7 @@ 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); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); diff --git a/test/mystery-encounter/encounters/part-timer-encounter.test.ts b/test/mystery-encounter/encounters/part-timer-encounter.test.ts index 36a92b2b6bf..1826c75381a 100644 --- a/test/mystery-encounter/encounters/part-timer-encounter.test.ts +++ b/test/mystery-encounter/encounters/part-timer-encounter.test.ts @@ -246,7 +246,7 @@ describe("Part-Timer - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 3); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); diff --git a/test/mystery-encounter/encounters/safari-zone.test.ts b/test/mystery-encounter/encounters/safari-zone.test.ts index ec43dcfb69b..dd41d08df38 100644 --- a/test/mystery-encounter/encounters/safari-zone.test.ts +++ b/test/mystery-encounter/encounters/safari-zone.test.ts @@ -119,7 +119,7 @@ describe("Safari Zone - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 1); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); diff --git a/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts b/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts index 4d006abc636..c88d77a8cf5 100644 --- a/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts +++ b/test/mystery-encounter/encounters/teleporting-hijinks-encounter.test.ts @@ -8,9 +8,7 @@ import { SpeciesId } from "#enums/species-id"; import { UiMode } from "#enums/ui-mode"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { TeleportingHijinksEncounter } from "#mystery-encounters/teleporting-hijinks-encounter"; -import { CommandPhase } from "#phases/command-phase"; import { MysteryEncounterPhase } from "#phases/mystery-encounter-phases"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, runSelectMysteryEncounterOption, @@ -157,7 +155,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 1); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); @@ -167,7 +165,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, defaultParty); await runMysteryEncounterToEnd(game, 1, undefined, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); }); it("should transport to a new area", async () => { @@ -229,7 +227,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); @@ -239,7 +237,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.TELEPORTING_HIJINKS, [SpeciesId.METAGROSS]); await runMysteryEncounterToEnd(game, 2, undefined, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); }); it("should transport to a new area", async () => { @@ -300,7 +298,7 @@ describe("Teleporting Hijinks - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 3, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); 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 ade98bfa99f..ae4eb0647ce 100644 --- a/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts +++ b/test/mystery-encounter/encounters/the-expert-breeder-encounter.test.ts @@ -12,8 +12,6 @@ import { MysteryEncounter } from "#mystery-encounters/mystery-encounter"; 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 { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase, @@ -157,7 +155,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { expect(successfullyLoaded).toBe(true); // Check usual battle stuff - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(scene.currentBattle.trainer).toBeDefined(); expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE); expect(scene.getPlayerParty().length).toBe(1); @@ -175,8 +173,8 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); + await game.phaseInterceptor.to("SelectModifierPhase"); const eggsAfter = scene.gameData.eggs; const commonEggs = scene.currentBattle.mysteryEncounter!.misc.pokemon1CommonEggs; @@ -242,7 +240,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { expect(successfullyLoaded).toBe(true); // Check usual battle stuff - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(scene.currentBattle.trainer).toBeDefined(); expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE); expect(scene.getPlayerParty().length).toBe(1); @@ -260,8 +258,8 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); + await game.phaseInterceptor.to("SelectModifierPhase"); const eggsAfter = scene.gameData.eggs; const commonEggs = scene.currentBattle.mysteryEncounter!.misc.pokemon2CommonEggs; @@ -324,7 +322,7 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { expect(successfullyLoaded).toBe(true); // Check usual battle stuff - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(scene.currentBattle.trainer).toBeDefined(); expect(scene.currentBattle.mysteryEncounter?.encounterMode).toBe(MysteryEncounterMode.TRAINER_BATTLE); expect(scene.getPlayerParty().length).toBe(1); @@ -342,8 +340,8 @@ describe("The Expert Pokémon Breeder - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 3, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); - await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); + await game.phaseInterceptor.to("SelectModifierPhase"); const eggsAfter = scene.gameData.eggs; const commonEggs = scene.currentBattle.mysteryEncounter!.misc.pokemon3CommonEggs; 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 3880c07c312..4011a850a08 100644 --- a/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts +++ b/test/mystery-encounter/encounters/the-pokemon-salesman-encounter.test.ts @@ -182,7 +182,7 @@ describe("The Pokemon Salesman - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 1); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); 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 3592e2dc774..06c4c3c1cee 100644 --- a/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts +++ b/test/mystery-encounter/encounters/the-strong-stuff-encounter.test.ts @@ -17,9 +17,7 @@ import { PokemonMove } from "#moves/pokemon-move"; import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { TheStrongStuffEncounter } from "#mystery-encounters/the-strong-stuff-encounter"; -import { CommandPhase } from "#phases/command-phase"; import { MovePhase } from "#phases/move-phase"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase, @@ -192,7 +190,7 @@ describe("The Strong Stuff - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(SpeciesId.SHUCKLE); expect(enemyField[0].summonData.statStages).toEqual([0, 1, 0, 1, 0, 0, 0]); @@ -230,7 +228,7 @@ describe("The Strong Stuff - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); 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 cf0ff7a94bd..814e2ee07fb 100644 --- a/test/mystery-encounter/encounters/the-winstrate-challenge-encounter.test.ts +++ b/test/mystery-encounter/encounters/the-winstrate-challenge-encounter.test.ts @@ -15,9 +15,7 @@ import { MysteryEncounter } from "#mystery-encounters/mystery-encounter"; 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 { PartyHealPhase } from "#phases/party-heal-phase"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { VictoryPhase } from "#phases/victory-phase"; import { runMysteryEncounterToEnd } from "#test/mystery-encounter/encounter-test-utils"; import { GameManager } from "#test/test-utils/game-manager"; @@ -262,7 +260,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.THE_WINSTRATE_CHALLENGE, defaultParty); await runMysteryEncounterToEnd(game, 1, undefined, true); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(scene.currentBattle.trainer).toBeDefined(); expect(scene.currentBattle.trainer!.config.trainerType).toBe(TrainerType.VICTOR); expect(scene.currentBattle.mysteryEncounter?.enemyPartyConfigs.length).toBe(4); @@ -295,7 +293,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { // Should have Macho Brace in the rewards await skipBattleToNextBattle(game, true); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -337,7 +335,7 @@ describe("The Winstrate Challenge - Mystery Encounter", () => { it("should have a Rarer Candy in the rewards", async () => { await game.runToMysteryEncounter(MysteryEncounterType.THE_WINSTRATE_CHALLENGE, defaultParty); await runMysteryEncounterToEnd(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); 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 7cc9a69b32d..fe0139be3a7 100644 --- a/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts +++ b/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts @@ -20,9 +20,7 @@ import { } from "#mystery-encounters/encounter-phase-utils"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { TrashToTreasureEncounter } from "#mystery-encounters/trash-to-treasure-encounter"; -import { CommandPhase } from "#phases/command-phase"; import { MovePhase } from "#phases/move-phase"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase, @@ -172,8 +170,8 @@ describe("Trash to Treasure - Mystery Encounter", () => { 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); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); + await game.phaseInterceptor.to("SelectModifierPhase"); const leftovers = scene.findModifier(m => m instanceof TurnHealModifier) as TurnHealModifier; expect(leftovers).toBeDefined(); @@ -221,7 +219,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(SpeciesId.GARBODOR); expect(enemyField[0].moveset).toEqual([ @@ -243,7 +241,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); diff --git a/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts b/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts index 5aadaf5c29a..e5b086ceba9 100644 --- a/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts +++ b/test/mystery-encounter/encounters/uncommon-breed-encounter.test.ts @@ -15,7 +15,6 @@ 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"; import { UncommonBreedEncounter } from "#mystery-encounters/uncommon-breed-encounter"; -import { CommandPhase } from "#phases/command-phase"; import { MovePhase } from "#phases/move-phase"; import { MysteryEncounterPhase } from "#phases/mystery-encounter-phases"; import { StatStageChangePhase } from "#phases/stat-stage-change-phase"; @@ -120,7 +119,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); @@ -147,7 +146,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(enemyField[0].species.speciesId).toBe(speciesToSpawn); @@ -199,7 +198,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 2); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); @@ -259,7 +258,7 @@ describe("Uncommon Breed - Mystery Encounter", () => { await runSelectMysteryEncounterOption(game, 3); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); expect(scene.ui.playError).not.toHaveBeenCalled(); // No error sfx, option is disabled expect(mysteryEncounterPhase.handleOptionSelect).not.toHaveBeenCalled(); expect(mysteryEncounterPhase.continueEncounter).not.toHaveBeenCalled(); diff --git a/test/mystery-encounter/encounters/weird-dream-encounter.test.ts b/test/mystery-encounter/encounters/weird-dream-encounter.test.ts index e2ec7ae514a..9f03b113d27 100644 --- a/test/mystery-encounter/encounters/weird-dream-encounter.test.ts +++ b/test/mystery-encounter/encounters/weird-dream-encounter.test.ts @@ -10,8 +10,6 @@ import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils" import * as EncounterTransformationSequence from "#mystery-encounters/encounter-transformation-sequence"; import * as MysteryEncounters from "#mystery-encounters/mystery-encounters"; import { WeirdDreamEncounter } from "#mystery-encounters/weird-dream-encounter"; -import { CommandPhase } from "#phases/command-phase"; -import { SelectModifierPhase } from "#phases/select-modifier-phase"; import { runMysteryEncounterToEnd, skipBattleRunMysteryEncounterRewardsPhase, @@ -116,8 +114,8 @@ describe("Weird Dream - Mystery Encounter", () => { const bstsPrior = pokemonPrior.map(species => species.getSpeciesForm().getBaseStatTotal()); await runMysteryEncounterToEnd(game, 1); - await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); + await game.phaseInterceptor.to("SelectModifierPhase"); const pokemonAfter = scene.getPlayerParty(); const bstsAfter = pokemonAfter.map(pokemon => pokemon.getSpeciesForm().getBaseStatTotal()); @@ -140,7 +138,7 @@ describe("Weird Dream - Mystery Encounter", () => { await game.runToMysteryEncounter(MysteryEncounterType.WEIRD_DREAM, defaultParty); await runMysteryEncounterToEnd(game, 1); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); @@ -187,7 +185,7 @@ describe("Weird Dream - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); const enemyField = scene.getEnemyField(); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(CommandPhase.name); + expect(game).toBeAtPhase("CommandPhase"); expect(enemyField.length).toBe(1); expect(scene.getEnemyParty().length).toBe(scene.getPlayerParty().length); }); @@ -197,7 +195,7 @@ describe("Weird Dream - Mystery Encounter", () => { await runMysteryEncounterToEnd(game, 2, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to("SelectModifierPhase", false); - expect(scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(SelectModifierPhase.name); + expect(game).toBeAtPhase("SelectModifierPhase"); await game.phaseInterceptor.to("SelectModifierPhase"); expect(scene.ui.getMode()).to.equal(UiMode.MODIFIER_SELECT); diff --git a/test/mystery-encounter/mystery-encounter.test.ts b/test/mystery-encounter/mystery-encounter.test.ts index ec27f7c6a48..d44e3dd2905 100644 --- a/test/mystery-encounter/mystery-encounter.test.ts +++ b/test/mystery-encounter/mystery-encounter.test.ts @@ -34,7 +34,7 @@ describe("Mystery Encounters", () => { ]); await game.phaseInterceptor.to(MysteryEncounterPhase, false); - expect(game.scene.phaseManager.getCurrentPhase()!.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); }); it("Encounters should not run on X1 waves", async () => { diff --git a/test/phases/mystery-encounter-phase.test.ts b/test/phases/mystery-encounter-phase.test.ts index a3dc779b02c..30ab977dbc6 100644 --- a/test/phases/mystery-encounter-phase.test.ts +++ b/test/phases/mystery-encounter-phase.test.ts @@ -3,7 +3,7 @@ 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 { MysteryEncounterOptionSelectedPhase, MysteryEncounterPhase } from "#phases/mystery-encounter-phases"; +import { MysteryEncounterOptionSelectedPhase } from "#phases/mystery-encounter-phases"; import { GameManager } from "#test/test-utils/game-manager"; import type { MessageUiHandler } from "#ui/message-ui-handler"; import type { MysteryEncounterUiHandler } from "#ui/mystery-encounter-ui-handler"; @@ -38,7 +38,7 @@ describe("Mystery Encounter Phases", () => { ]); await game.phaseInterceptor.to("MysteryEncounterPhase", false); - expect(game.scene.phaseManager.getCurrentPhase()?.constructor.name).toBe(MysteryEncounterPhase.name); + expect(game).toBeAtPhase("MysteryEncounterPhase"); }); it("Runs MysteryEncounterPhase", async () => { diff --git a/test/status-effects/general-status-effect.test.ts b/test/status-effects/general-status-effect.test.ts new file mode 100644 index 00000000000..db73265181b --- /dev/null +++ b/test/status-effects/general-status-effect.test.ts @@ -0,0 +1,60 @@ +import { allAbilities } from "#data/data-lists"; +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 { ObtainStatusEffectPhase } from "#phases/obtain-status-effect-phase"; +import { GameManager } from "#test/test-utils/game-manager"; +import type { PostAttackContactApplyStatusEffectAbAttr } from "#types/ability-types"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from "vitest"; + +describe("Status Effects - General", () => { + 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") + .enemyLevel(5) + .enemySpecies(SpeciesId.MAGIKARP) + .enemyAbility(AbilityId.BALL_FETCH) + .enemyMoveset(MoveId.SPLASH) + .ability(AbilityId.BALL_FETCH); + }); + + test("multiple status effects from the same interaction should not overwrite each other", async () => { + game.override.ability(AbilityId.POISON_TOUCH).moveset([MoveId.NUZZLE]); + await game.classicMode.startBattle([SpeciesId.PIKACHU]); + + // Force poison touch to always apply + vi.spyOn( + allAbilities[AbilityId.POISON_TOUCH].getAttrs( + "PostAttackContactApplyStatusEffectAbAttr", + // expose chance, which is private, for testing purpose, but keep type safety otherwise + )[0] as unknown as Omit & { chance: number }, + "chance", + "get", + ).mockReturnValue(100); + const statusEffectPhaseSpy = vi.spyOn(ObtainStatusEffectPhase.prototype, "start"); + + game.move.select(MoveId.NUZZLE); + await game.toEndOfTurn(); + + expect(statusEffectPhaseSpy).toHaveBeenCalledOnce(); + const enemy = game.field.getEnemyPokemon(); + // This test does not care which status effect is applied, as long as one is. + expect(enemy.status?.effect).toBeOneOf([StatusEffect.POISON, StatusEffect.PARALYSIS]); + }); +}); diff --git a/test/test-utils/game-manager.ts b/test/test-utils/game-manager.ts index 57badd866b1..5f56832a6d2 100644 --- a/test/test-utils/game-manager.ts +++ b/test/test-utils/game-manager.ts @@ -44,6 +44,7 @@ import type { InputsHandler } from "#test/test-utils/inputs-handler"; import { MockFetch } from "#test/test-utils/mocks/mock-fetch"; import { PhaseInterceptor } from "#test/test-utils/phase-interceptor"; import { TextInterceptor } from "#test/test-utils/text-interceptor"; +import type { PhaseClass, PhaseString } from "#types/phase-types"; import type { BallUiHandler } from "#ui/ball-ui-handler"; import type { BattleMessageUiHandler } from "#ui/battle-message-ui-handler"; import type { CommandUiHandler } from "#ui/command-ui-handler"; @@ -160,7 +161,7 @@ export class GameManager { * End the currently running phase immediately. */ endPhase() { - this.scene.phaseManager.getCurrentPhase()?.end(); + this.scene.phaseManager.getCurrentPhase().end(); } /** @@ -412,10 +413,11 @@ export class GameManager { * Checks if the current phase matches the target phase. * @param phaseTarget - The target phase. * @returns Whether the current phase matches the target phase + * @todo Remove `phaseClass` from signature */ - isCurrentPhase(phaseTarget) { + isCurrentPhase(phaseTarget: PhaseClass | PhaseString) { const targetName = typeof phaseTarget === "string" ? phaseTarget : phaseTarget.name; - return this.scene.phaseManager.getCurrentPhase()?.constructor.name === targetName; + return this.scene.phaseManager.getCurrentPhase().phaseName === targetName; } /** diff --git a/test/test-utils/helpers/classic-mode-helper.ts b/test/test-utils/helpers/classic-mode-helper.ts index 008648fcd0d..c625ebc911c 100644 --- a/test/test-utils/helpers/classic-mode-helper.ts +++ b/test/test-utils/helpers/classic-mode-helper.ts @@ -1,6 +1,7 @@ import { getGameMode } from "#app/game-mode"; import overrides from "#app/overrides"; import { BattleStyle } from "#enums/battle-style"; +import { Button } from "#enums/buttons"; import { GameModes } from "#enums/game-modes"; import { Nature } from "#enums/nature"; import type { SpeciesId } from "#enums/species-id"; @@ -100,4 +101,33 @@ export class ClassicModeHelper extends GameManagerHelper { await this.game.phaseInterceptor.to(CommandPhase); console.log("==================[New Turn]=================="); } + + /** + * Queue inputs to switch at the start of the next battle, and then start it. + * @param pokemonIndex - The 0-indexed position of the party pokemon to switch to. + * Should never be called with 0 as that will select the currently active pokemon and freeze + * @returns A Promise that resolves once the battle has been started and the switch prompt resolved + * @todo Make this work for double battles + * @example + * ```ts + * await game.classicMode.runToSummon([SpeciesId.MIGHTYENA, SpeciesId.POOCHYENA]) + * await game.startBattleWithSwitch(1); + * ``` + */ + public async startBattleWithSwitch(pokemonIndex: number): Promise { + this.game.scene.battleStyle = BattleStyle.SWITCH; + this.game.onNextPrompt( + "CheckSwitchPhase", + UiMode.CONFIRM, + () => { + this.game.scene.ui.getHandler().setCursor(0); + this.game.scene.ui.getHandler().processInput(Button.ACTION); + }, + () => this.game.isCurrentPhase("CommandPhase") || this.game.isCurrentPhase("TurnInitPhase"), + ); + this.game.doSelectPartyPokemon(pokemonIndex); + + await this.game.phaseInterceptor.to("CommandPhase"); + console.log("==================[New Battle (Initial Switch)]=================="); + } } diff --git a/test/test-utils/matchers/to-be-at-phase.ts b/test/test-utils/matchers/to-be-at-phase.ts new file mode 100644 index 00000000000..7ff76fa0365 --- /dev/null +++ b/test/test-utils/matchers/to-be-at-phase.ts @@ -0,0 +1,45 @@ +/** biome-ignore-start lint/correctness/noUnusedImports: TSDoc imports */ +import type { Phase } from "#app/phase"; +import type { GameManager } from "#test/test-utils/game-manager"; +// biome-ignore-end lint/correctness/noUnusedImports: TSDoc + +import { isGameManagerInstance, receivedStr } from "#test/test-utils/test-utils"; +import type { PhaseString } from "#types/phase-types"; +import type { MatcherState, SyncExpectationResult } from "@vitest/expect"; + +/** + * Matcher that checks if the current {@linkcode Phase} is of the given type. + * @param received - The object to check. Should be the current {@linkcode GameManager} + * @param expectedPhase - The expected {@linkcode PhaseString} + * @returns The result of the matching + */ +export function toBeAtPhase(this: MatcherState, received: unknown, expectedPhase: PhaseString): SyncExpectationResult { + if (!isGameManagerInstance(received)) { + return { + pass: this.isNot, + message: () => `Expected to receive a GameManager, but got ${receivedStr(received)}!`, + }; + } + + if (!received.scene?.phaseManager) { + return { + pass: this.isNot, + message: () => `Expected GameManager.${received.scene ? "scene.phaseManager" : "scene"} to be defined!`, + }; + } + + const currPhase = received.scene.phaseManager.getCurrentPhase(); + const pass = currPhase.is(expectedPhase); + + const actual = currPhase.phaseName; + + return { + pass, + message: () => + pass + ? `Expected the current phase to NOT be ${expectedPhase}, but it was!` + : `Expected the current phase to be ${expectedPhase}, but got ${actual} instead!`, + expected: expectedPhase, + actual, + }; +} diff --git a/test/test-utils/matchers/to-have-arena-tag.ts b/test/test-utils/matchers/to-have-arena-tag.ts index e2a4a71ffd5..a9d619686d1 100644 --- a/test/test-utils/matchers/to-have-arena-tag.ts +++ b/test/test-utils/matchers/to-have-arena-tag.ts @@ -6,11 +6,21 @@ import type { OneOther } from "#test/@types/test-helpers"; import type { GameManager } from "#test/test-utils/game-manager"; import { getOnelineDiffStr } from "#test/test-utils/string-utils"; import { isGameManagerInstance, receivedStr } from "#test/test-utils/test-utils"; +import type { ArenaTagDataMap, SerializableArenaTagType } from "#types/arena-tags"; import type { MatcherState, SyncExpectationResult } from "@vitest/expect"; -// intersection required to preserve T for inferences -export type toHaveArenaTagOptions = OneOther & { - tagType: T; +/** + * Options type for {@linkcode toHaveArenaTag}. + * @typeParam A - The {@linkcode ArenaTagType} being checked + * @remarks + * If A corresponds to a serializable `ArenaTag`, only properties allowed to be serialized + * (i.e. can change across instances) will be present and able to be checked. + */ +export type toHaveArenaTagOptions = OneOther< + A extends SerializableArenaTagType ? ArenaTagDataMap[A] : ArenaTagTypeMap[A], + "tagType" | "side" +> & { + tagType: A; }; /** @@ -22,10 +32,10 @@ export type toHaveArenaTagOptions = OneOther( +export function toHaveArenaTag( this: MatcherState, received: unknown, - expectedTag: T | toHaveArenaTagOptions, + expectedTag: A | toHaveArenaTagOptions, side: ArenaTagSide = ArenaTagSide.BOTH, ): SyncExpectationResult { if (!isGameManagerInstance(received)) { diff --git a/test/test-utils/matchers/to-have-battler-tag.ts b/test/test-utils/matchers/to-have-battler-tag.ts index af405d7da39..ba6679b2af4 100644 --- a/test/test-utils/matchers/to-have-battler-tag.ts +++ b/test/test-utils/matchers/to-have-battler-tag.ts @@ -3,21 +3,39 @@ import type { Pokemon } from "#field/pokemon"; /* biome-ignore-end lint/correctness/noUnusedImports: tsdoc imports */ import { getPokemonNameWithAffix } from "#app/messages"; +import type { BattlerTagTypeMap } from "#data/battler-tags"; import { BattlerTagType } from "#enums/battler-tag-type"; -import { getEnumStr } from "#test/test-utils/string-utils"; +import type { OneOther } from "#test/@types/test-helpers"; +import { getEnumStr, getOnelineDiffStr } from "#test/test-utils/string-utils"; import { isPokemonInstance, receivedStr } from "#test/test-utils/test-utils"; +import type { BattlerTagDataMap, SerializableBattlerTagType } from "#types/battler-tags"; import type { MatcherState, SyncExpectationResult } from "@vitest/expect"; +// intersection required to preserve T for inferences /** - * Matcher that checks if a {@linkcode Pokemon} has a specific {@linkcode BattlerTagType}. + * Options type for {@linkcode toHaveBattlerTag}. + * @typeParam B - The {@linkcode BattlerTagType} being checked + * @remarks + * If B corresponds to a serializable `BattlerTag`, only properties allowed to be serialized + * (i.e. can change across instances) will be present and able to be checked. + */ +export type toHaveBattlerTagOptions = (B extends SerializableBattlerTagType + ? OneOther + : OneOther) & { + tagType: B; +}; + +/** + * Matcher that checks if a {@linkcode Pokemon} has a specific {@linkcode BattlerTag}. * @param received - The object to check. Should be a {@linkcode Pokemon} - * @param expectedBattlerTagType - The {@linkcode BattlerTagType} to check for + * @param expectedTag - The `BattlerTagType` of the desired tag, or a partially-filled object + * containing the desired properties * @returns Whether the matcher passed */ -export function toHaveBattlerTag( +export function toHaveBattlerTag( this: MatcherState, received: unknown, - expectedBattlerTagType: BattlerTagType, + expectedTag: B | toHaveBattlerTagOptions, ): SyncExpectationResult { if (!isPokemonInstance(received)) { return { @@ -26,18 +44,44 @@ export function toHaveBattlerTag( }; } - const pass = !!received.getTag(expectedBattlerTagType); const pkmName = getPokemonNameWithAffix(received); - // "BattlerTagType.SEEDED (=1)" - const expectedTagStr = getEnumStr(BattlerTagType, expectedBattlerTagType, { prefix: "BattlerTagType." }); + // Coerce lone `tagType`s into objects + const etag = typeof expectedTag === "object" ? expectedTag : { tagType: expectedTag }; + const gotTag = received.getTag(etag.tagType); + + // If checking exclusively tag type OR no tags were found, break out early. + if (typeof expectedTag !== "object" || !gotTag) { + const pass = !!gotTag; + // "BattlerTagType.SEEDED (=1)" + const expectedTagStr = getEnumStr(BattlerTagType, etag.tagType, { prefix: "BattlerTagType." }); + + return { + pass, + message: () => + pass + ? `Expected ${pkmName} to NOT have a tag of type ${expectedTagStr}, but it did!` + : `Expected ${pkmName} to have a tag of type ${expectedTagStr}, but it didn't!`, + expected: expectedTag, + actual: received.summonData.tags.map(t => t.tagType), + }; + } + + // Check for equality with the provided tag + const pass = this.equals(gotTag, etag, [ + ...this.customTesters, + this.utils.subsetEquality, + this.utils.iterableEquality, + ]); + + const expectedStr = getOnelineDiffStr.call(this, expectedTag); return { pass, message: () => pass - ? `Expected ${pkmName} to NOT have ${expectedTagStr}, but it did!` - : `Expected ${pkmName} to have ${expectedTagStr}, but it didn't!`, - expected: expectedBattlerTagType, - actual: received.summonData.tags.map(t => t.tagType), + ? `Expected ${pkmName} to NOT have a tag matching ${expectedStr}, but it did!` + : `Expected ${pkmName} to have a tag matching ${expectedStr}, but it didn't!`, + expected: expectedTag, + actual: gotTag, }; } diff --git a/test/test-utils/phase-interceptor.ts b/test/test-utils/phase-interceptor.ts index 0d357a75557..cc8d9b8e32a 100644 --- a/test/test-utils/phase-interceptor.ts +++ b/test/test-utils/phase-interceptor.ts @@ -37,6 +37,7 @@ import { NewBiomeEncounterPhase } from "#phases/new-biome-encounter-phase"; import { NextEncounterPhase } from "#phases/next-encounter-phase"; import { PartyExpPhase } from "#phases/party-exp-phase"; import { PartyHealPhase } from "#phases/party-heal-phase"; +import { PokemonHealPhase } from "#phases/pokemon-heal-phase"; import { PokemonTransformPhase } from "#phases/pokemon-transform-phase"; import { PositionalTagPhase } from "#phases/positional-tag-phase"; import { PostGameOverPhase } from "#phases/post-game-over-phase"; @@ -181,6 +182,7 @@ export class PhaseInterceptor { UnlockPhase, PostGameOverPhase, RevivalBlessingPhase, + PokemonHealPhase, ]; private endBySetMode = [ @@ -382,7 +384,7 @@ export class PhaseInterceptor { const actionForNextPrompt = this.prompts[0]; const expireFn = actionForNextPrompt.expireFn?.(); const currentMode = this.scene.ui.getMode(); - const currentPhase = this.scene.phaseManager.getCurrentPhase()?.constructor.name; + const currentPhase = this.scene.phaseManager.getCurrentPhase().phaseName; const currentHandler = this.scene.ui.getHandler(); if (expireFn) { this.prompts.shift(); diff --git a/test/test-utils/string-utils.ts b/test/test-utils/string-utils.ts index 6c29c04c107..e19224f4571 100644 --- a/test/test-utils/string-utils.ts +++ b/test/test-utils/string-utils.ts @@ -183,5 +183,5 @@ export function getOnelineDiffStr(this: MatcherState, obj: unknown): string { return this.utils .stringify(obj, undefined, { maxLength: 35, indent: 0, printBasicPrototype: false }) .replace(/\n/g, " ") // Replace newlines with spaces - .replace(/,(\s*)}$/g, "$1}"); // Trim trailing commas + .replace(/,(\s*)\}$/g, "$1}"); // Trim trailing commas } diff --git a/test/ui/item-manage-button.test.ts b/test/ui/item-manage-button.test.ts index a7ea76918a5..c28cd9e802e 100644 --- a/test/ui/item-manage-button.test.ts +++ b/test/ui/item-manage-button.test.ts @@ -6,7 +6,7 @@ import { UiMode } from "#enums/ui-mode"; import type { Pokemon } from "#field/pokemon"; import { GameManager } from "#test/test-utils/game-manager"; import type { ModifierSelectUiHandler } from "#ui/modifier-select-ui-handler"; -import type { PartyUiHandler } from "#ui/party-ui-handler"; +import { type PartyUiHandler, PartyUiMode } from "#ui/party-ui-handler"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; @@ -169,4 +169,51 @@ describe("UI - Transfer Items", () => { expect(pokemon.getHeldItems().map(h => h.stackCount)).toEqual([2, 2]); } }); + + // TODO: This test breaks when running all tests on github. Fix this once hotfix period is over. + it.todo("should not allow changing to discard mode when transfering items", async () => { + let handler: PartyUiHandler | undefined; + + const { resolve, promise } = Promise.withResolvers(); + + game.onNextPrompt("SelectModifierPhase", UiMode.MODIFIER_SELECT, async () => { + await new Promise(r => setTimeout(r, 100)); + const modifierHandler = game.scene.ui.getHandler() as ModifierSelectUiHandler; + + modifierHandler.processInput(Button.DOWN); + modifierHandler.setCursor(1); + modifierHandler.processInput(Button.ACTION); + }); + + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + handler = game.scene.ui.getHandler() as PartyUiHandler; + + handler.setCursor(0); + handler.processInput(Button.ACTION); + + await new Promise(r => setTimeout(r, 100)); + handler.processInput(Button.ACTION); + + resolve(); + }); + + await promise; + expect(handler).toBeDefined(); + if (handler) { + const partyMode = handler["partyUiMode"]; + expect(partyMode).toBe(PartyUiMode.MODIFIER_TRANSFER); + + handler.setCursor(7); + handler.processInput(Button.ACTION); + // Should not change mode to discard + expect(handler["partyUiMode"]).toBe(PartyUiMode.MODIFIER_TRANSFER); + + handler.processInput(Button.CANCEL); + handler.setCursor(7); + handler.processInput(Button.ACTION); + // Should change mode to discard + expect(handler["partyUiMode"]).toBe(PartyUiMode.DISCARD); + } + }); }); diff --git a/test/ui/transfer-item-options.test.ts b/test/ui/transfer-item-options.test.ts new file mode 100644 index 00000000000..901aa261f50 --- /dev/null +++ b/test/ui/transfer-item-options.test.ts @@ -0,0 +1,235 @@ +import { BerryType } from "#enums/berry-type"; +import { Button } from "#enums/buttons"; +import { MoveId } from "#enums/move-id"; +import { SpeciesId } from "#enums/species-id"; +import { UiMode } from "#enums/ui-mode"; +import { GameManager } from "#test/test-utils/game-manager"; +import { type PartyUiHandler, PartyUiMode } from "#ui/party-ui-handler"; +import type { RenameFormUiHandler } from "#ui/rename-form-ui-handler"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +// todo: Some tests fail when running all tests at once, but pass when running individually. Seams like it's always the 2nd and 4th (non todo) tests that fail. +describe("UI - Transfer Item Options", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(async () => { + game = new GameManager(phaserGame); + game.override + .battleStyle("single") + .startingLevel(100) + .startingHeldItems([ + { name: "BERRY", count: 1, type: BerryType.SITRUS }, + { name: "BERRY", count: 2, type: BerryType.APICOT }, + { name: "BERRY", count: 2, type: BerryType.LUM }, + ]) + .enemySpecies(SpeciesId.MAGIKARP) + .enemyMoveset(MoveId.SPLASH); + + await game.classicMode.startBattle([SpeciesId.BULBASAUR, SpeciesId.SQUIRTLE, SpeciesId.CHARMANDER]); + + game.move.use(MoveId.DRAGON_CLAW); + + await game.phaseInterceptor.to("SelectModifierPhase"); + await game.scene.ui.setModeWithoutClear(UiMode.PARTY, PartyUiMode.MODIFIER_TRANSFER); + }); + + it.todo("should open the summary screen while transfering an item", async () => { + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // Select first party member + handler.setCursor(0); + handler.processInput(Button.ACTION); + + resolve(); + }); + }); + + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + // select item to transfer + handler.processInput(Button.ACTION); + resolve(); + }); + }); + + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // move to second pokemon + handler.setCursor(1); + handler.processInput(Button.ACTION); + + // select summary + handler.processInput(Button.DOWN); + handler.processInput(Button.ACTION); + + await new Promise(r => setTimeout(r, 100)); + expect(game.scene.ui.getMode()).toBe(UiMode.SUMMARY); + }); + + it.todo("should open the pokèdex screen while transfering an item", async () => { + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // Select first party member + handler.setCursor(0); + handler.processInput(Button.ACTION); + + resolve(); + }); + }); + + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + // select item to transfer + handler.processInput(Button.ACTION); + resolve(); + }); + }); + + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + // move to second pokemon + handler.setCursor(1); + handler.processInput(Button.ACTION); + + // select pokèdex + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.ACTION); + + await new Promise(r => setTimeout(r, 100)); + expect(game.scene.ui.getMode()).toBe(UiMode.POKEDEX_PAGE); + }); + + it.todo("should open the rename screen and rename the pokemon while transfering an item", async () => { + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // Select first party member + handler.setCursor(0); + handler.processInput(Button.ACTION); + + resolve(); + }); + }); + + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + // select item to transfer + handler.processInput(Button.ACTION); + resolve(); + }); + }); + + await new Promise(r => setTimeout(r, 100)); + let handler: PartyUiHandler | RenameFormUiHandler | undefined; + handler = game.scene.ui.getHandler() as PartyUiHandler; + + // move to second pokemon + handler.setCursor(1); + handler.processInput(Button.ACTION); + + // select rename + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.ACTION); + + const pokemon = game.scene.getPlayerParty()[1]; + if (!pokemon) { + expect.fail("Pokemon is undefined"); + } + const nickname = pokemon.nickname; + + expect(nickname).toBe(undefined); + + await new Promise(r => setTimeout(r, 100)); + expect(game.scene.ui.getMode()).toBe(UiMode.RENAME_POKEMON); + await new Promise(r => setTimeout(r, 100)); + handler = game.scene.ui.getHandler() as RenameFormUiHandler; + handler["inputs"][0].setText("New nickname"); + handler.processInput(Button.SUBMIT); + await new Promise(r => setTimeout(r, 100)); + // get the sanitized name + const sanitizedName = btoa(unescape(encodeURIComponent("New nickname"))); + expect(pokemon.nickname).toBe(sanitizedName); + }); + + it.todo("should pause the evolution while transfering an item", async () => { + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // Select first party member + handler.setCursor(0); + handler.processInput(Button.ACTION); + + resolve(); + }); + }); + + await new Promise(resolve => { + game.onNextPrompt("SelectModifierPhase", UiMode.PARTY, async () => { + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + // select item to transfer + handler.processInput(Button.ACTION); + resolve(); + }); + }); + + await new Promise(r => setTimeout(r, 100)); + const handler = game.scene.ui.getHandler() as PartyUiHandler; + + // move to second pokemon + handler.setCursor(1); + handler.processInput(Button.ACTION); + + const pokemon = game.scene.getPlayerParty()[1]; + + if (!pokemon) { + expect.fail("Pokemon is undefined"); + } + if (pokemon.pauseEvolutions !== undefined) { + expect(pokemon.pauseEvolutions).toBe(false); + } + + // select pause evolution + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.DOWN); + handler.processInput(Button.ACTION); + + await new Promise(r => setTimeout(r, 100)); + expect(game.scene.ui.getMode()).toBe(UiMode.PARTY); + expect(pokemon.pauseEvolutions).toBe(true); + }); +}); diff --git a/test/utils/data.test.ts b/test/utils/data.test.ts new file mode 100644 index 00000000000..c0b853e2643 --- /dev/null +++ b/test/utils/data.test.ts @@ -0,0 +1,39 @@ +import { deepCopy, isBareObject } from "#utils/data"; +import { describe, expect, it } from "vitest"; + +describe("Utils - Data", () => { + describe("deepCopy", () => { + it("should create a deep copy of an object", () => { + const original = { a: 1, b: { c: 2 } }; + const copy = deepCopy(original); + // ensure the references are different + expect(copy === original, "copied object should not compare equal").not; + expect(copy).toEqual(original); + // update copy's `a` to a different value and ensure original is unaffected + copy.a = 42; + expect(original.a, "adjusting property of copy should not affect original").toBe(1); + // update copy's nested `b.c` to a different value and ensure original is unaffected + copy.b.c = 99; + expect(original.b.c, "adjusting nested property of copy should not affect original").toBe(2); + }); + }); + + describe("isBareObject", () => { + it("should properly identify bare objects", () => { + expect(isBareObject({}), "{} should be considered bare"); + expect(isBareObject(new Object()), "new Object() should be considered bare"); + expect(isBareObject(Object.create(null))); + expect(isBareObject([]), "an empty array should be considered bare"); + }); + + it("should properly reject non-objects", () => { + expect(isBareObject(new Date())).not; + expect(isBareObject(null)).not; + expect(isBareObject(42)).not; + expect(isBareObject("")).not; + expect(isBareObject(undefined)).not; + expect(isBareObject(() => {})).not; + expect(isBareObject(new (class A {})())).not; + }); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index dcbf7456df8..8becb4c00ec 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -59,5 +59,12 @@ "outDir": "./build", "noEmit": true }, - "exclude": ["node_modules", "dist", "vite.config.ts", "vitest.config.ts", "vitest.workspace.ts"] + "exclude": [ + "node_modules", + "dist", + "vite.config.ts", + "vitest.config.ts", + "vitest.workspace.ts", + "public/service-worker.js" + ] } diff --git a/typedoc-plugins/typedoc-plugin-rename-svg.js b/typedoc-plugins/typedoc-plugin-rename-svg.js new file mode 100644 index 00000000000..5fda4ee3c6d --- /dev/null +++ b/typedoc-plugins/typedoc-plugin-rename-svg.js @@ -0,0 +1,34 @@ +// @ts-check + +import { PageKind, Renderer } from "typedoc"; + +/** + * @module + * Typedoc plugin to run post-processing on the `index.html` file and replace the coverage SVG + * for Beta with the newly generated file for the current branch. + */ + +/** + * @param {import('typedoc').Application} app + */ +export function load(app) { + // Don't do anything if no REF_NAME was specified (likely indicating a local docs run) + if (!process.env.REF_NAME) { + return; + } + app.renderer.on(Renderer.EVENT_END_PAGE, page => { + if (page.pageKind === PageKind.Index && page.contents) { + page.contents = page.contents + // Replace links to the beta documentation site with the current ref name + .replace( + /href="(.*pagefaultgames.github.io\/pokerogue\/).*?"/, // formatting + `href="$1/${process.env.REF_NAME}"`, + ) + // Replace the link to Beta's coverage SVG with the SVG file for the branch in question. + .replace( + /img src=".*?coverage.svg/, // formatting + `img src="coverage.svg"`, + ); + } + }); +} diff --git a/typedoc.config.js b/typedoc.config.js new file mode 100644 index 00000000000..1f944cd544e --- /dev/null +++ b/typedoc.config.js @@ -0,0 +1,58 @@ +import { globSync } from "node:fs"; + +const dryRun = !!process.env.DRY_RUN?.match(/true/gi); + +/** + * @type {Partial} + */ +const config = { + entryPoints: ["./src", "./test/test-utils"], + entryPointStrategy: "expand", + exclude: ["**/*+.test.ts", "src/polyfills.ts", "src/vite.env.d.ts"], + excludeReferences: true, // prevent documenting re-exports + requiredToBeDocumented: [ + "Enum", + "EnumMember", + "Variable", + "Function", + "Class", + "Interface", + "Property", + "Method", + "Accessor", + "TypeAlias", + ], + highlightLanguages: ["javascript", "json", "jsonc", "json5", "tsx", "typescript", "markdown"], + plugin: [ + "typedoc-github-theme", + "typedoc-plugin-coverage", + "typedoc-plugin-mdn-links", + ...globSync("./typedoc-plugins/**/*.js").map(plugin => "./" + plugin), + ], + // Avoid emitting docs for branches other than main/beta + emit: dryRun ? "none" : "docs", + out: process.env.CI ? "/tmp/docs" : "./typedoc", + name: "PokéRogue", + readme: "./README.md", + coverageLabel: "Documented", + coverageSvgWidth: 120, // Increased from 104 baseline due to adding 2 extra letters + favicon: "./public/images/logo.png", + theme: "typedoc-github-theme", + customFooterHtml: "

Copyright Pagefault Games 2025

", + customFooterHtmlDisableWrapper: true, + navigationLinks: { + GitHub: "https://github.com/pagefaultgames/pokerogue", + }, +}; + +// If generating docs for main/beta, check the ref name and add an appropriate navigation header +if (!dryRun && process.env.REF_NAME) { + const otherRefName = process.env.REF_NAME === "main" ? "beta" : "main"; + config.navigationLinks = { + ...config.navigationLinks, + // This will be "Switch to Beta" when on main, and vice versa + [`Switch to ${otherRefName.charAt(0).toUpperCase() + otherRefName.slice(1).toLowerCase()}`]: `https://pagefaultgames.github.io/pokerogue/${otherRefName}`, + }; +} + +export default config; diff --git a/typedoc.json b/typedoc.json deleted file mode 100644 index c34e6190c1a..00000000000 --- a/typedoc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "entryPoints": ["./src"], - "entryPointStrategy": "expand", - "exclude": ["**/*+.test.ts"], - "out": "typedoc", - "highlightLanguages": ["javascript", "json", "jsonc", "json5", "tsx", "typescript", "markdown"] -}